summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-11-18 23:40:08 -0500
committerFox Caminiti <fox@foxcam.net>2022-11-18 23:40:08 -0500
commit990bd319c696c2b65fa858b40fd75279fec2a13b (patch)
tree0ba0e29e2a1af31e7257d3cc48198f244415d120
parentbb4d634962cdf97affd041a81b12c3d2c8d46bf7 (diff)
txt2img functional
-rwxr-xr-xbuild.sh2
-rw-r--r--createcalls.cpp2
-rw-r--r--defines.h4
-rw-r--r--functions.h2
-rw-r--r--lib/base64.c11
-rw-r--r--main.cpp54
-rw-r--r--main.h9
-rw-r--r--memory.cpp179
-rw-r--r--my_imgui_widgets.cpp74
-rw-r--r--stable_diffusion.cpp248
-rw-r--r--stable_diffusion.h15
-rw-r--r--undo.cpp48
12 files changed, 405 insertions, 243 deletions
diff --git a/build.sh b/build.sh
index 1e4f865..e0df0d4 100755
--- a/build.sh
+++ b/build.sh
@@ -118,7 +118,7 @@ clang lib/glad.c $GLAD_FLAGS -I/usr/local/include -I/opt/local/include -c \
$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 \
+ -std=c++11 -lstdc++ -lcurl -Iimgui -Iimgui/backends \
$SDL_ARGS \
-I . \
-lm -I /usr/local/include $(pkg-config --cflags --libs $FFMPEG_LIBS)
diff --git a/createcalls.cpp b/createcalls.cpp
index 85faa3c..e88e39f 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -266,7 +266,7 @@ void Clipboard_Store(project_data *File, project_state *State, memory *Memory, s
for (int p = 0; p < Property->Keyframe_Count; p++) {
bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[p]);
if (PointAddress->IsSelected) {
- Arbitrary_WriteInto((uint8 *)PointAddress, (uint8 *)State->ClipboardBuffer + ClipboardPos, sizeof(bezier_point));
+ Memory_Copy((uint8 *)State->ClipboardBuffer + ClipboardPos, (uint8 *)PointAddress, sizeof(bezier_point));
ClipboardPos += sizeof(bezier_point);
Channel->KeyframeCount++;
}
diff --git a/defines.h b/defines.h
index fd63c30..1e8a933 100644
--- a/defines.h
+++ b/defines.h
@@ -42,8 +42,8 @@ typedef uint64 ptrsize; // is there a compiler variable for 32 vs 64 bit like
#define AmountOf(Array) sizeof((Array)) / sizeof((Array)[1])
#if ARM
-#define GetTime() Assert(0)
+#define GetCPUTime() Assert(0)
#else
-#define GetTime() __rdtsc()
+#define GetCPUTime() __rdtsc()
#endif
diff --git a/functions.h b/functions.h
index a1f5d2a..69ce817 100644
--- a/functions.h
+++ b/functions.h
@@ -1,6 +1,6 @@
// static bool32 AV_IsFileSupported(char *filename, bool32 *IsVideo);
-static void Arbitrary_WriteInto(uint8 *Address_Read, uint8 *Address_Write, uint64 Size);
+static void Memory_Copy(uint8 *Address_Write, uint8 *Address_Read, uint64 Size);
static void Arbitrary_Zero(uint8 *Address_Write, uint64 Size);
static void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size);
static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction);
diff --git a/lib/base64.c b/lib/base64.c
index 1e7e192..b6a8e5d 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -1,3 +1,5 @@
+// Slightly moulded by Fox to better suit his (poor?) tastes.
+
/*
The compilation of software known as FreeBSD is distributed under the
following terms:
@@ -122,7 +124,7 @@ void base64_encode(const unsigned char *src, size_t len,
* Caller is responsible for freeing the returned buffer.
*/
unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+ unsigned char *out_buffer, size_t *out_len)
{
unsigned char dtable[256], *out, *pos, block[4], tmp;
size_t i, count, olen;
@@ -148,11 +150,8 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
return NULL;
olen = count / 4 * 3;
- // pos = out = os_malloc(olen);
- pos = out = NULL;
- Assert(0);
- if (out == NULL)
- return NULL;
+ pos = out = out_buffer;
+ Assert(out != NULL)
count = 0;
for (i = 0; i < len; i++) {
diff --git a/main.cpp b/main.cpp
index 85dd002..3cc976c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -33,6 +33,8 @@
#define STBI_FAILURE_USERMSG
#include "lib/stb_image.h"
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "lib/stb_image_write.h"
#include "defines.h"
#include "my_math.h"
@@ -60,6 +62,7 @@ static instruction_mode InstructionMode = instruction_mode_scalar;
static uint32 RandomGlobalIncrement = 0;
#include "lib/base64.c"
+#include <curl/curl.h>
#include "memory.cpp"
#include "undo.cpp"
@@ -242,7 +245,8 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui_File(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray);
ImGui_PropertiesPanel(File, State, UI, Memory, io);
ImGui_ColorPanel(File, State, UI, Memory, io);
- ImGui_StableDiffusion(File, State, UI, Memory, io);
+ ImGui_SD_Prompt(File, State, UI, Memory, io);
+ ImGui_SD_Thumbnail(File, State, UI, Memory, io);
ImGui_Menu(File, State, UI, Memory, io);
File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize);
@@ -281,7 +285,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
// if (Entry_Main->IsCached)
// return CompBuffer;
- uint64 Comp_TimeStart = GetTime();
+ uint64 Comp_TimeStart = GetCPUTime();
sorted_comp_info *SortedCompInfo = &SortedCompArray[CompIndex];
sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex);
@@ -356,7 +360,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
} else {
cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0);
if (!Entry->IsCached) {
- uint64 Src_TimeStart = GetTime();
+ uint64 Src_TimeStart = GetCPUTime();
block_string *Name = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Source->Path_String_Index);
int w = 0, h = 0;
void *temp = stbi_load(Name->Char, &w, &h, NULL, 4);
@@ -365,11 +369,11 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
Source->BytesPerPixel = 4;
uint64 Size = Source->Width * Source->Height * Source->BytesPerPixel;
void *Source_Address = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
- Arbitrary_WriteInto((uint8 *)temp, (uint8 *)Source_Address, Size);
+ Memory_Copy((uint8 *)Source_Address, (uint8 *)temp, Size);
stbi_image_free(temp);
BitmapState->ToUpdate = false;
BitmapState->CurrentFrame = 0;
- Entry->CycleTime = GetTime() - Src_TimeStart;
+ Entry->CycleTime = GetCPUTime() - Src_TimeStart;
Layer->x.CurrentValue = Comp->Width/2;
Layer->y.CurrentValue = Comp->Height/2;
Entry->IsCached = true;
@@ -405,7 +409,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
Render_Main((void *)&T, CompBuffer, render_type_main, RenderRegion);
}
}
- Entry_Main->CycleTime = GetTime() - Comp_TimeStart;
+ Entry_Main->CycleTime = GetCPUTime() - Comp_TimeStart;
Entry_Main->IsCached = true;
return CompBuffer;
}
@@ -503,6 +507,9 @@ int main(int argc, char *argv[]) {
State->Brush.TransientBitmap = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
ScratchPaintSize = 2048*2048*4;
Memory.ScratchPos += ScratchPaintSize;
+ State->Dump1 = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
+ Memory.ScratchPos += ScratchPaintSize;
+ State->Dump2 = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
State->ClipboardBuffer = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
State->ClipboardSize = 1024*1024;
@@ -852,12 +859,47 @@ int main(int argc, char *argv[]) {
Brush_CalcBitmapAlphaFromSize(&Memory, &State->Brush, 4);
State_BindBrushTexture(&Memory, &State->Brush, 4);
+ curl_global_init(CURL_GLOBAL_ALL);
+ curl_state MainHandle = {};
+ curl_state ProgHandle = {};
+ uint32 Inc = 0;
while (State->IsRunning)
{
// State->Interact_Active = interact_type_layer_move;
// State->Interact_Offset[1] = -3.0f;
+ if (State->CurlActive) {
+ if (State->CurlActive == -1) {
+ Curl_GET_Init(&MainHandle, State->Dump1, State->JSONPayload, State->SD.ServerAddress, State->SD.Mode);
+ Curl_Prog_Init(&ProgHandle, State->Dump2);
+ State->CurlActive = 1;
+ } else {
+ if (Curl_Check(&MainHandle) == 1) {
+ SD_JSONToSource(File, State, &Memory, State->Dump1, State->SD.Height, State->SD.Width);
+ Curl_Free(&ProgHandle);
+ curl_slist_free_all(ProgHandle.list);
+ Curl_Free(&MainHandle);
+ State->CurlActive = 0;
+ }
+ uint64 Time = ImGui::GetTime();
+ if (Time - State->SDTimer > 0.3f) {
+ if (Curl_Check(&ProgHandle) == 1) {
+ SD_ParseProgress(State, (char *)State->Dump2);
+ curl_multi_remove_handle(ProgHandle.curlm, ProgHandle.curl);
+ curl_easy_reset(ProgHandle.curl);
+ ProgHandle.CurlData.size = 0;
+ curl_easy_setopt(ProgHandle.curl, CURLOPT_URL, "http://127.0.0.1:7860/sdapi/v1/progress");
+ curl_easy_setopt(ProgHandle.curl, CURLOPT_WRITEFUNCTION, dumbcurlcallback);
+ curl_easy_setopt(ProgHandle.curl, CURLOPT_WRITEDATA, (void *)&ProgHandle.CurlData);
+ curl_multi_add_handle(ProgHandle.curlm, ProgHandle.curl);
+ }
+ State->SDTimer = Time;
+ }
+ Inc++;
+ }
+ }
+
Main_InputTest(File, State, &Memory, &UI, window, textureID);
if (State->IsPlaying) {
diff --git a/main.h b/main.h
index e0a9374..3d7b3e5 100644
--- a/main.h
+++ b/main.h
@@ -315,6 +315,14 @@ struct project_state
brush_state Brush;
sd_state SD;
+ char JSONPayload[1024];
+ int32 CurlActive = 0;
+ real32 SDPercentDone;
+ real32 SDTimeEstimate;
+ real64 SDTimer;
+
+ void *Dump1;
+ void *Dump2;
char DummyName2[512];
@@ -369,6 +377,7 @@ struct block_composition
enum source_type {
source_type_none,
source_type_principal,
+ source_type_principal_temp,
source_type_file
};
diff --git a/memory.cpp b/memory.cpp
index 4593d49..64aadc1 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -1,3 +1,4 @@
+
static void
Memory_InitTable(global_memory *GlobalMemory, memory *Memory, uint64 Size, memory_table_list TableName, char *Name, uint64 Block_ElementSize = 0) {
memory_table *Table = &Memory->Slot[TableName];
@@ -250,166 +251,48 @@ Memory_AddressAtOffset(memory *Memory, memory_table_list TableName, uint64 Offse
return (void *)((uint8 *)Table->Address + Offset);
}
-#if 0
-static void*
-AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) {
- void *Address;
- memory_table *Table = &Memory->Slot[TableName];
- if (Table->CurrentPosition + Size > Table->Size) {
- return NULL;
- }
- Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition);
- Table->CurrentPosition += Size;
- return Address;
-}
-
-// Returns the address without advancing
-static void*
-Memory_GetAddressAt(memory *Memory, uint64 Size, memory_table_list TableName) {
- void *Address;
- memory_table *Table = &Memory->Slot[TableName];
- if (Table->CurrentPosition + Size > Table->Size) {
- return NULL;
+void Memory_Copy(uint8 *Address_Write, uint8 *Address_Read, uint64 Size)
+{
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = *(Address_Read + i);
+ i++;
}
- Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition + Size);
- return Address;
-}
-
-// Returns the address and THEN advances
-static void*
-Memory_Advance(memory *Memory, uint64 Size, memory_table_list TableName) {
- return AllocateMemory(Memory, Size, TableName);
}
-// Rewinds and THEN returns the address
-static void*
-Memory_Rewind(memory *Memory, uint64 Size, memory_table_list TableName) {
- void *Address;
- memory_table *Table = &Memory->Slot[TableName];
- if (Table->CurrentPosition - Size < 0) {
- return NULL;
+void Arbitrary_Zero(uint8 *Address_Write, uint64 Size)
+{
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = 0;
+ i++;
}
- Table->CurrentPosition -= Size;
- Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition);
- 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)
+void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size)
{
- real32 Result = 0;
- uint64 TotalSize = Amount*Size;
- uint64 PointerLocationSize = (uint8 *)Pointer - (uint8 *)StartingPointer;
- Result = (real32)PointerLocationSize / (real32)TotalSize;
- return Result;
+ uint8 *Buffer_Scratch = (uint8 *)Memory_PushScratch(Memory, Size);
+ Memory_Copy(Buffer_Scratch, Address_0, Size);
+ Memory_Copy(Address_0, Address_1, Size);
+ Memory_Copy(Address_1, Buffer_Scratch, Size);
+ Memory_PopScratch(Memory, Size);
}
-static void
-Debug_Memory_Assert_Cohesion(memory *Memory, memory_table *Table)
-{
-#if DEBUG
- for (uint32 i = 0; i < Table->NumberOfPointers; i++) {
- cached_bitmap *CurrentBitmap = &Memory->Bitmap[i];
- Assert(CurrentBitmap->Data);
- for (uint32 a = 0; a < Table->NumberOfPointers; a++) {
- if (a == i) {
- continue;
- }
- cached_bitmap *OtherBitmap = &Memory->Bitmap[a];
- if (OtherBitmap->Data == CurrentBitmap->Data) {
- Assert(0);
- }
- }
- }
-#else
-#endif
-}
-static cached_bitmap *
-Memory_RollingBitmap(memory *Memory, source *Source, uint32 FrameToSeek)
+static void
+Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction)
{
- uint16 Width = Source->Info.Width;
- uint16 Height = Source->Info.Height;
- uint16 BytesPerPixel = Source->Info.BytesPerPixel;
-
- memory_table *Table = &Memory->Slot[B_LoadedBitmaps];
-
- // First check whether we'd run over the buffer at the current
- // position, and reset the position if so.
- 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 there are no pointers in front of us, we don't have to free any space
- // and just need to increment the number of pointers.
- if (Table->PointerIndex != Table->NumberOfPointers) {
- // Next, if there's a pointer in front of the current position,
- // check whether it's far away enough so that the size fits.
- bool32 BS = true;
- if (Bitmap->Data) {
- uint64 BytesBetween = (uint8 *)Bitmap->Data - ((uint8 *)Table->Address + Table->CurrentPosition);
- if (BytesBetween > Size) {
- uint32 StopAt = Table->NumberOfPointers - 1;
- while (StopAt > Table->PointerIndex - 1) {
- Memory->Bitmap[StopAt + 1] = Memory->Bitmap[StopAt];
- StopAt--;
- }
- Table->NumberOfPointers++;
- BS = false;
- }
- }
- // If it doesn't fit, then we need to dereference the pointers
- // until we have enough space.
- if ((Table->PointerIndex < Table->NumberOfPointers) && BS)
- {
- bool32 Avail = false;
- void *AddressStart = (void *)((uint8 *)Table->Address + Table->CurrentPosition);
- uint32 Amount = 0;
- while(!Avail) {
- // Bail out if we're on the last index, as we don't need to do anything else.
- // TODO(fox): This could be simplified if we compared
- // pointer start plus data instead of just the start.
- if (Table->PointerIndex != Table->NumberOfPointers - 1) {
- void *Data2 = Memory->Bitmap[Table->PointerIndex+1].Data;
- uint64 BytesBetween = (uint8 *)Data2 - (uint8 *)AddressStart;
- if (BytesBetween < Size) {
- uint32 StopAt = Table->PointerIndex;
- while (StopAt < Table->NumberOfPointers - 1) {
- Memory->Bitmap[StopAt] = Memory->Bitmap[StopAt + 1];
- StopAt++;
- }
- Amount++;
- Table->NumberOfPointers--;
- if (Amount > 2) {
- Amount += 0;
- }
- } else {
- Avail = true;
- }
- } else {
- Avail = true;
- }
- }
+ if (Direction > 0) {
+ uint8 *AddressPlayhead = Address_End;
+ while ((ptrsize)AddressPlayhead >= (ptrsize)Address_Start) {
+ *(AddressPlayhead + ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead--;
}
} else {
- Table->NumberOfPointers++;
- }
- Bitmap->Data = AllocateMemory(Memory, Size, B_LoadedBitmaps);
- if (!Bitmap->Data) {
- Assert(0);
+ uint8 *AddressPlayhead = Address_Start;
+ while ((ptrsize)AddressPlayhead < (ptrsize)Address_End) {
+ *(AddressPlayhead - ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead++;
+ }
}
- Bitmap->SourceOwner = Source;
- Bitmap->Frame = FrameToSeek;
- Table->PointerIndex++;
-
- // No two pointers on the table should hold the same data
- // address or be empty.
- Debug_Memory_Assert_Cohesion(Memory, Table);
- return Bitmap;
}
-#endif
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index bfe114b..b3339d2 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -35,7 +35,7 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
bool32 Display = 1;
block_layer *Layer = NULL;
if (State->MostRecentlySelectedLayer > -1) {
- Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->MostRecentlySelectedLayer);
+ Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->MostRecentlySelectedLayer, 0);
if (!Layer->Occupied)
Display = 0;
} else {
@@ -237,28 +237,57 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io,
}
static void
-ImGui_StableDiffusion(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
+ImGui_SD_Thumbnail(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
+{
+ ImGui::Begin("SD gallery");
+ ImGui::End();
+}
+
+static void
+ImGui_SD_Prompt(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
{
ImGui::Begin("SD prompt input");
sd_state *SD = &State->SD;
int Size = ImGui::GetFontSize();
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(200, 80, 0, 255));
if (ImGui::Button("Generate!", ImVec2(Size*8, Size*2))) {
- /*
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
- block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
- cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0);
- Assert(Entry->IsCached);
- void *BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
- uint64 Size = Source->Width * Source->Height * Source->BytesPerPixel;
- uint64 EncodedLength = 0;
- uint64 EncodedAllocSize = base64_encode_size(Size);
- void *EncodedOutput = Memory_PushScratch(Memory, EncodedSize);
- uint64 EncodedTrueSize;
- base64_encode((uint8 *)BitmapAddress, Size, (uint8 *)EncodedOutput, &EncodedTrueSize);
- Memory_PopScratch(Memory, EncodedSize);
- */
- SD_Txt2Txt(SD);
+ if (!State->CurlActive) {
+ if (SD->Mode) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
+ cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0);
+ Assert(Entry->IsCached);
+ void *BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
+ uint64 Size = Source->Width * Source->Height * Source->BytesPerPixel;
+
+ int32 len = 0;
+ uint8 *PNGBitmap = stbi_write_png_to_mem((uint8 *)BitmapAddress, Source->Width * Source->BytesPerPixel,
+ Source->Width, Source->Height, Source->BytesPerPixel, &len);
+ Assert(PNGBitmap);
+
+ uint64 EncodedLength = 0;
+ uint64 EncodedAllocSize = base64_encode_size(Size);
+ uint8 *EncodedOutput = (uint8 *)Memory_PushScratch(Memory, EncodedAllocSize);
+ uint64 EncodedTrueSize;
+
+ base64_encode((uint8 *)BitmapAddress, Size, EncodedOutput, &EncodedTrueSize);
+ Assert(EncodedOutput[EncodedTrueSize] == '\0');
+
+ STBIW_FREE(PNGBitmap);
+
+ SD_AssembleJSON(SD, (char *)State->Dump1, EncodedOutput);
+ Memory_PopScratch(Memory, EncodedAllocSize);
+ } else {
+ SD_AssembleJSON(SD, State->JSONPayload);
+ // SD_AssembleJSON(SD, (char *)State->Dump2);
+ }
+ State->CurlActive = -1;
+ }
+ }
+ ImGui::PopStyleColor();
+ if (State->CurlActive) {
+ ImGui::SameLine();
+ ImGui::Text("Est. time: %.1f sec, %.2f", State->SDTimeEstimate, State->SDPercentDone*100);
}
ImGui::InputText("Address", SD->ServerAddress, SD_LEN_ADDRESS);
if (State->Initializing && (SD->ServerAddress[0] == '\0')) {
@@ -266,7 +295,10 @@ ImGui_StableDiffusion(project_data *File, project_state *State, ui *UI, memory *
sprintf(SD->NegPrompt, "%s", "nsfw, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark");
sprintf(SD->ServerAddress, "%s", "http://127.0.0.1:7860");
}
- ImGui::PopStyleColor();
+ if (ImGui::Selectable("txt2img", !SD->Mode))
+ SD->Mode = 0;
+ if (ImGui::Selectable("img2img", SD->Mode))
+ SD->Mode = 1;
ImGui::InputTextMultiline("Prompt", SD->Prompt, SD_LEN_PROMPT);
ImGui::InputTextMultiline("Negative prompt", SD->NegPrompt, SD_LEN_PROMPT);
ImGui::SliderInt("Steps", &SD->Steps, 0, 150);
@@ -279,7 +311,9 @@ ImGui_StableDiffusion(project_data *File, project_state *State, ui *UI, memory *
SD->Height = SD->Height + (64 - (SD->Height % 64));
}
ImGui::SliderFloat("CFG scale", &SD->CFG, 1, 30, "%.2f");
- ImGui::SliderFloat("Denoising strength", &SD->DenoisingStrength, 0, 1, "%.2f");
+ if (SD->Mode) {
+ ImGui::SliderFloat("Denoising strength", &SD->DenoisingStrength, 0, 1, "%.2f");
+ }
ImGui::InputInt("Seed", &SD->Seed);
ImGui::End();
}
@@ -840,7 +874,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
bool32 IsHovered = ImGui::IsItemHovered();
-#if 0
+#if 1
bool32 IsActive = ImGui::IsItemActive();
bool32 IsActivated = ImGui::IsItemActivated();
#else
diff --git a/stable_diffusion.cpp b/stable_diffusion.cpp
index 0c42f03..2eb230b 100644
--- a/stable_diffusion.cpp
+++ b/stable_diffusion.cpp
@@ -1,15 +1,121 @@
+struct curl_data {
+ char *response;
+ size_t size;
+};
+
+static size_t dumbcurlcallback(void *data, size_t size, size_t nmemb, void *userp)
+ {
+ size_t realsize = size * nmemb;
+ curl_data *mem = (curl_data *)userp;
+
+ Memory_Copy((uint8 *)&(mem->response[mem->size]), (uint8 *)data, realsize);
+ mem->size += realsize;
+ mem->response[mem->size] = 0;
+
+ return realsize;
+ }
+
+static void
+SD_JSONToSource(project_data *File, project_state *State, memory *Memory, void *JSONResponse, int Height, int Width)
+{
+ // We've gotta go from base64 to compressed PNG to the raw format we want.
+ uint8 *Data = (uint8 *)JSONResponse;
+ uint64 i = 0;
+ Assert(Data[2] != 'd');
+ while (Data[i] != '[')
+ i++;
+ i += 2;
+ Assert(Data[i] != '"');
+ uint64 UncompressedSize = Width * Height * 4;
+ uint64 c = 0;
+ while (Data[i+c] != ']')
+ c++;
+ uint64 MaxSize = Width * Height * 4;
+ void *PNGData = Memory_PushScratch(Memory, MaxSize);
+ uint64 PNGSize = 0;
+ base64_decode(&Data[i], c, (uint8 *)PNGData, &PNGSize);
+ int x, y, a;
+ void *RawData = stbi_load_from_memory((stbi_uc *)PNGData, PNGSize, &x, &y, &a, 4);
+ Assert(x == Width && y == Height);
+ Memory_PopScratch(Memory, MaxSize);
+ int SrcIdx = Source_Generate_Blank(File, State, Memory, Width, Height, 4);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, SrcIdx);
+ // Source->Type = source_type_principal_temp;
+ void *BitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index, 0);
+ Memory_Copy((uint8 *)BitmapAddress, (uint8 *)RawData, MaxSize);
+ stbi_image_free(RawData);
+}
static void
-SD_Txt2Txt(sd_state *SD)
+SD_ParseProgress(project_state *State, char *JSONInfo)
{
- char JSONPayload[1024];
- char CurlCommand[1024];
+ char P[4];
+ char P2[8];
+ int ProgLocation = 0;
+ while (!(JSONInfo[ProgLocation] == 's' && JSONInfo[ProgLocation+1] == 's')) {
+ ProgLocation++;
+ }
+ ProgLocation += 4;
+ int ETALocation = ProgLocation;
+ while (!(JSONInfo[ETALocation] == 'v' && JSONInfo[ETALocation+1] == 'e')) {
+ ETALocation++;
+ }
+ ETALocation += 4;
+ // Assert(JSONInfo[ProgLocation] >= '0' && JSONInfo[ProgLocation] <= '9');
+ // Assert(JSONInfo[ETALocation] >= '0' && JSONInfo[ETALocation] <= '9');
+ Memory_Copy((uint8 *)P, (uint8 *)&JSONInfo[12], 4);
+ Memory_Copy((uint8 *)P2, (uint8 *)&JSONInfo[32], 8);
+ real32 Percent = atof(P);
+ if (Percent > 0.0f) // occasionally returns negative
+ State->SDPercentDone = Percent;
+ real32 Time = atof(P2);
+ if (Time > 0.1f) // occasionally returns zero for some reason
+ State->SDTimeEstimate = Time;
+ // Assert(0);
+}
+
+static void
+JSON_AppendParam_String(char *String, uint64 *i, char *P1, char *P2)
+{
+ uint64 c = *i;
+ String[c++] = '"';
+ int a = 0;
+ while(P1[a] != '\0') {
+ String[c++] = P1[a++];
+ }
+ String[c++] = ':';
+ String[c++] = ' ';
+ String[c++] = '"';
+ a = 0;
+ while(P2[a] != '\0') {
+ String[c++] = P2[a++];
+ if (a > 64)
+ break;
+ }
+ c--;
+ String[c++] = '"';
+ String[c++] = ',';
+ String[c++] = '\n';
+ String[c++] = '\0';
+ *i = c;
+}
+
+static void
+SD_AssembleJSON(sd_state *SD, char *JSONPayload, void *Base64Bitmap = NULL)
+{
+ Arbitrary_Zero((uint8 *)JSONPayload, 1024);
+ // char CurlCommand[1024];
char *Test[] = { "prompt", "negative_prompt", "steps", "width", "height", "cfg_scale" };
void *Test2[6] = { (void *)SD->Prompt, (void *)SD->NegPrompt,
(void *)&SD->Steps, (void *)&SD->Width,
(void *)&SD->Height, (void *)&SD->CFG };
int Type[6] = { 0, 0, 1, 1, 1, 2};
- sprintf(JSONPayload, "%s{\n", JSONPayload);
+ JSONPayload[0] = '{';
+ JSONPayload[1] = '\n';
+ JSONPayload[2] = '\0';
+ uint64 i = 2;
+ if (SD->Mode)
+ JSON_AppendParam_String(JSONPayload, &i, "init_images", (char *)Base64Bitmap);
for (int i = 0; i < 6; i++) {
if (Type[i] == 0) {
sprintf(JSONPayload, "%s\"%s\": \"%s\",\n", JSONPayload, Test[i], (char *)Test2[i]);
@@ -21,8 +127,136 @@ SD_Txt2Txt(sd_state *SD)
Assert(0);
}
}
+ if (SD->Mode)
+ sprintf(JSONPayload, "%s\"%s\": %.2f,\n", JSONPayload, "denoising_strength", SD->DenoisingStrength);
+ sprintf(JSONPayload, "%s%s\n", JSONPayload, "\"sampler_index\": \"DDIM\"");
sprintf(JSONPayload, "%s}\n", JSONPayload);
- sprintf(CurlCommand, "curl -X POST -H 'Content-Type: application/json' -i '%s/sdapi/v1/txt2img' --data '%s'",
- SD->ServerAddress, JSONPayload);
- printf("%s\n", CurlCommand);
+ // sprintf(CurlCommand, "curl -X POST -H 'Content-Type: application/json' -i '%s/sdapi/v1/txt2img' --data '%s'", SD->ServerAddress, JSONPayload);
+ // printf("%s\n", CurlCommand);
};
+
+struct curl_state
+{
+ CURL *curl;
+ CURLM *curlm;
+ curl_slist *list = NULL;
+ curl_data CurlData;
+};
+
+static void
+Curl_Free(curl_state *Handle)
+{
+ curl_multi_remove_handle(Handle->curlm, Handle->curl);
+ curl_easy_cleanup(Handle->curl);
+ curl_multi_cleanup(Handle->curlm);
+}
+
+static bool32
+Curl_Check(curl_state *Handle)
+{
+ int IsActive;
+ CURLMcode mc = curl_multi_perform(Handle->curlm, &IsActive);
+ Assert(!mc);
+ if (!IsActive) {
+ int queue = 0;
+ CURLMsg *msg = curl_multi_info_read(Handle->curlm, &queue);
+ if (msg) {
+ CURL *e = msg->easy_handle;
+ Assert(e == Handle->curl);
+ Assert(msg->msg == CURLMSG_DONE);
+ if (!msg->data.result) {
+ return 1;
+ } else if (msg->data.result == CURLE_COULDNT_CONNECT) {
+ // printf("Active stable-diffusion-webui instance not found at URL.\n");
+ return -1;
+ } else {
+ // printf("curl error: %s!\n", curl_easy_strerror(msg->data.result));
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static char *APIString[] = {"txt2img", "img2img" };
+
+static void
+Curl_GET_Init(curl_state *C, void *OutputData, char *JSONPayload, char *IP, bool32 API)
+{
+ C->list = curl_slist_append(C->list, "Content-Type: application/json");
+
+ C->curl = curl_easy_init();
+ Assert(C->curl);
+
+ char URL[512];
+ sprintf(URL, "%s/sdapi/v1/%s", IP, APIString[API]);
+ curl_easy_setopt(C->curl, CURLOPT_URL, URL);
+ curl_easy_setopt(C->curl, CURLOPT_HTTPHEADER, C->list);
+ curl_easy_setopt(C->curl, CURLOPT_POSTFIELDS, JSONPayload);
+
+ C->CurlData = { (char *)OutputData, 0 };
+
+ curl_easy_setopt(C->curl, CURLOPT_WRITEFUNCTION, dumbcurlcallback);
+ curl_easy_setopt(C->curl, CURLOPT_WRITEDATA, (void *)&C->CurlData);
+
+ C->curlm = curl_multi_init();
+ Assert(C->curlm);
+ curl_multi_add_handle(C->curlm, C->curl);
+
+ Curl_Check(C);
+}
+
+static void
+Curl_Prog_Init(curl_state *C, void *OutputData)
+{
+ C->curl = curl_easy_init();
+ Assert(C->curl);
+
+ C->CurlData = { (char *)OutputData, 0 };
+
+ curl_easy_setopt(C->curl, CURLOPT_URL, "http://127.0.0.1:7860/sdapi/v1/progress");
+ curl_easy_setopt(C->curl, CURLOPT_WRITEFUNCTION, dumbcurlcallback);
+ curl_easy_setopt(C->curl, CURLOPT_WRITEDATA, (void *)&C->CurlData);
+
+ C->curlm = curl_multi_init();
+ Assert(C->curlm);
+ curl_multi_add_handle(C->curlm, C->curl);
+}
+
+ /*
+ int num;
+ CURLMcode mc = curl_multi_perform(C->curlm, &num);
+ Assert(!mc);
+
+ int queue = 0;
+ CURLMsg *msg = curl_multi_info_read(C->curlm, &queue);
+ if (msg) {
+ CURL *e = msg->easy_handle;
+ if (msg->msg == CURLMSG_DONE) {
+ if (msg->data.result == CURLE_COULDNT_CONNECT) {
+ printf("Active stable-diffusion-webui instance not found at URL.\n");
+ } else {
+ printf("curl error: %s!\n", curl_easy_strerror(msg->data.result));
+ }
+ Assert(0);
+ }
+ }
+ */
+
+
+#if 0
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* Perform the request, res will get the return code */
+
+ /* always cleanup */
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+
+
+ curl_global_cleanup();
+#endif
diff --git a/stable_diffusion.h b/stable_diffusion.h
index 6e7dd54..97ae076 100644
--- a/stable_diffusion.h
+++ b/stable_diffusion.h
@@ -9,17 +9,24 @@
#define SD_LEN_PROMPT 256
#define SD_LEN_ADDRESS 128
+// struct sd_mode
+// {
+// sd_mode_txt2txt,
+// sd_mode_txt2img
+// }
+
struct sd_state
{
+ bool32 Mode = 1;
char Prompt[256];
char NegPrompt[256];
char ServerAddress[128];
- int32 Steps = 25;
- int32 Width = 512;
- int32 Height = 512;
+ int32 Steps = 10;
+ int32 Width = 384;
+ int32 Height = 384;
int32 SamplerIndex = 0;
real32 CFG = 7;
- real32 DenoisingStrength = 0.7;
+ real32 DenoisingStrength = 0.2;
int32 Seed = -1;
};
diff --git a/undo.cpp b/undo.cpp
index a86e214..e568675 100644
--- a/undo.cpp
+++ b/undo.cpp
@@ -1,49 +1,3 @@
-void Arbitrary_WriteInto(uint8 *Address_Read, uint8 *Address_Write, uint64 Size)
-{
- uint64 i = 0;
- while (i < Size) {
- *(Address_Write + i) = *(Address_Read + i);
- i++;
- }
-}
-
-void Arbitrary_Zero(uint8 *Address_Write, uint64 Size)
-{
- uint64 i = 0;
- while (i < Size) {
- *(Address_Write + i) = 0;
- i++;
- }
-}
-
-void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size)
-{
- uint8 *Buffer_Scratch = (uint8 *)Memory_PushScratch(Memory, Size);
- Arbitrary_WriteInto(Address_0, Buffer_Scratch, Size);
- Arbitrary_WriteInto(Address_1, Address_0, Size);
- Arbitrary_WriteInto(Buffer_Scratch, Address_1, Size);
- Memory_PopScratch(Memory, Size);
-}
-
-
-static void
-Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction)
-{
- if (Direction > 0) {
- uint8 *AddressPlayhead = Address_End;
- while ((ptrsize)AddressPlayhead >= (ptrsize)Address_Start) {
- *(AddressPlayhead + ShiftAmount) = *AddressPlayhead;
- AddressPlayhead--;
- }
- } else {
- uint8 *AddressPlayhead = Address_Start;
- while ((ptrsize)AddressPlayhead < (ptrsize)Address_End) {
- *(AddressPlayhead - ShiftAmount) = *AddressPlayhead;
- AddressPlayhead++;
- }
- }
-}
-
struct history_info {
uint16 ActionCount_Total;
uint16 ActionCount_EndOfPlayhead;
@@ -249,7 +203,7 @@ static void History_Action_Add(memory *Memory, history_action ActionData, void *
{
void *Address_HistoryTree = Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
void *Address_Data = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);
- Arbitrary_WriteInto((uint8 *)Address_Data, (uint8 *)Address_HistoryTree, Action->Size);
+ Memory_Copy((uint8 *)Address_HistoryTree, (uint8 *)Address_Data, Action->Size);
} else if (Action->Type == action_type_shift)
{
void *Address_Start = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);