Browse Source

Textures: Add ImTextureUserID_Invalid + introducing SetTexID().

Which gives us room for potentially updating ImDrawData during render.
ocornut 7 months ago
parent
commit
ee357aaddf
2 changed files with 18 additions and 9 deletions
  1. 15 6
      imgui.h
  2. 3 3
      imgui_draw.cpp

+ 15 - 6
imgui.h

@@ -318,6 +318,11 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
 typedef ImU64 ImTextureID;  // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that)
 #endif
 
+// Define this to another value if you need value of 0 to be valid.
+#ifndef ImTextureID_Invalid
+#define ImTextureID_Invalid     ((ImTextureID)0)
+#endif
+
 // ImTextureRef contains:
 // -    a texture/atlas pointer, typically when created by Dear ImGui itself.
 // - OR a raw ImTextureID value (user/backend identifier), typically when created by user code to load images.
@@ -3362,21 +3367,19 @@ struct ImTextureRect
 // - void*          BackendUserData = higher-level opaque storage for backend own book-keeping. Some backends may have enough with TexID and not need both.
 struct IMGUI_API ImTextureData
 {
-    ImTextureStatus     Status;                 // ImTextureStatus_OK/_WantCreate/_WantUpdates/_WantDestroy
+    ImTextureStatus     Status;                 // ImTextureStatus_OK/_WantCreate/_WantUpdates/_WantDestroy. Always use SetStatus() to modify!
     ImTextureFormat     Format;                 // ImTextureFormat_RGBA32 (default) or ImTextureFormat_Alpha8
     int                 Width;                  // Texture width
     int                 Height;                 // Texture height
     int                 BytesPerPixel;          // 4 or 1
     int                 UniqueID;               // Sequential index to facilitate identifying a texture when debugging/printing. Only unique per atlas.
     unsigned char*      Pixels;                 // Pointer to buffer holding 'Width*Height' pixels and 'Width*Height*BytesPerPixels' bytes.
-    ImTextureID         TexID;                  // Identifier stored in ImDrawCmd::GetTexID() and passed to backend RenderDrawData loop.
+    ImTextureID         TexID;                  // Always use SetTexID() to modify! Identifier stored in ImDrawCmd::GetTexID() and passed to backend RenderDrawData loop.
     void*               BackendUserData;        // Convenience storage for backend. Some backends may have enough with TexID.
     ImTextureRect       UpdateRect;             // Bounding box encompassing all individual updates.
     ImVector<ImTextureRect> Updates;            // Array of individual updates.
     int                 UnusedFrames;           // In order to facilitate handling Status==WantDestroy in some backend: this is a count successive frames where the texture was not used. Always >0 when Status==WantDestroy.
-
-    // [Internal]
-    bool                UseColors;              // [Internal] Tell whether our texture data is known to use colors (rather than just white + alpha).
+    bool                UseColors;              // Tell whether our texture data is known to use colors (rather than just white + alpha).
     bool                WantDestroyNextFrame;   // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
 
     // Functions
@@ -3390,6 +3393,10 @@ struct IMGUI_API ImTextureData
     int                 GetPitch() const            { return Width * BytesPerPixel; }
     ImTextureRef        GetTexRef() const           { ImTextureRef tex_ref; tex_ref._TexData = (ImTextureData*)(void*)this; tex_ref._TexID = TexID; return tex_ref; }
     ImTextureID         GetTexID() const            { return TexID; }
+
+    // Called by Renderer backend
+    void                SetTexID(ImTextureID tex_id)      { TexID = tex_id; }   // Call after creating or destroying the texture. Never modify TexID directly!
+    void                SetStatus(ImTextureStatus status) { Status = status; }  // Call after honoring a request. Never modify Status directly!
 };
 
 //-----------------------------------------------------------------------------
@@ -3689,9 +3696,11 @@ struct ImFont
 // FIXME-NEWATLAS: Added indirection to avoid patching ImDrawCmd after texture updates.
 inline ImTextureID ImDrawCmd::GetTexID() const
 {
+    // If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92)
+    // must iterate and handle ImTextureData requests stored in ImDrawData::Textures[].
     ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID;
     if (TexRef._TexData != NULL)
-        IM_ASSERT(tex_id && "ImDrawCmd is referring to Atlas texture that wasn't uploaded to graphics system.");
+        IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
     return tex_id;
 }
 

+ 3 - 3
imgui_draw.cpp

@@ -2695,7 +2695,7 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas)
 
         if (tex->Status == ImTextureStatus_Destroyed)
         {
-            IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == NULL);
+            IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL);
             if (tex->WantDestroyNextFrame)
                 remove_from_list = true; // Destroy was scheduled by us
             else
@@ -2715,7 +2715,7 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas)
             tex->UnusedFrames++;
 
         // If a texture has never reached the backend, they don't need to know about it.
-        if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == 0 && tex->BackendUserData == NULL)
+        if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
             remove_from_list = true;
 
         // Remove
@@ -3518,7 +3518,7 @@ ImTextureData* ImFontAtlasBuildAddTexture(ImFontAtlas* atlas, int w, int h)
     /*if (old_tex != NULL && old_tex->Status == ImTextureStatus_WantCreate)
     {
         // Reuse texture not yet used by backend.
-        IM_ASSERT(old_tex->TexID == 0 && old_tex->BackendUserData == NULL);
+        IM_ASSERT(old_tex->TexID == ImTextureID_Invalid && old_tex->BackendUserData == NULL);
         old_tex->DestroyPixels();
         old_tex->Updates.clear();
         new_tex = old_tex;