From 82f20cdcc0a48435fa3ba3f0d4ff4ecbb30da450 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= <rverschelde@gmail.com>
Date: Mon, 7 Aug 2023 15:34:07 +0200
Subject: astcenc: Update to 4.7.0

https://github.com/ARM-software/astc-encoder/releases/tag/4.5.0
https://github.com/ARM-software/astc-encoder/releases/tag/4.6.0
https://github.com/ARM-software/astc-encoder/releases/tag/4.7.0
---
 thirdparty/astcenc/astcenc_internal_entry.h | 71 ++++++++++++++++++++++++++---
 1 file changed, 64 insertions(+), 7 deletions(-)

(limited to 'thirdparty/astcenc/astcenc_internal_entry.h')

diff --git a/thirdparty/astcenc/astcenc_internal_entry.h b/thirdparty/astcenc/astcenc_internal_entry.h
index 4e8794547a..2667714781 100644
--- a/thirdparty/astcenc/astcenc_internal_entry.h
+++ b/thirdparty/astcenc/astcenc_internal_entry.h
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: Apache-2.0
 // ----------------------------------------------------------------------------
-// Copyright 2011-2022 Arm Limited
+// Copyright 2011-2024 Arm Limited
 //
 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
 // use this file except in compliance with the License. You may obtain a copy
@@ -118,6 +118,18 @@ private:
 	/** @brief Number of tasks that need to be processed. */
 	unsigned int m_task_count;
 
+	/** @brief Progress callback (optional). */
+	astcenc_progress_callback m_callback;
+
+	/** @brief Lock used for callback synchronization. */
+	std::mutex m_callback_lock;
+
+	/** @brief Minimum progress before making a callback. */
+	float m_callback_min_diff;
+
+	/** @brief Last progress callback value. */
+	float m_callback_last_value;
+
 public:
 	/** @brief Create a new ParallelManager. */
 	ParallelManager()
@@ -138,6 +150,8 @@ public:
 		m_start_count = 0;
 		m_done_count = 0;
 		m_task_count = 0;
+		m_callback_last_value = 0.0f;
+		m_callback_min_diff = 1.0f;
 	}
 
 	/**
@@ -166,14 +180,20 @@ public:
 	 * initialization. Other threads will block and wait for it to complete.
 	 *
 	 * @param task_count   Total number of tasks needing processing.
+	 * @param callback     Function pointer for progress status callbacks.
 	 */
-	void init(unsigned int task_count)
+	void init(unsigned int task_count, astcenc_progress_callback callback)
 	{
 		std::lock_guard<std::mutex> lck(m_lock);
 		if (!m_init_done)
 		{
+			m_callback = callback;
 			m_task_count = task_count;
 			m_init_done = true;
+
+			// Report every 1% or 4096 blocks, whichever is larger, to avoid callback overhead
+			float min_diff = (4096.0f / static_cast<float>(task_count)) * 100.0f;
+			m_callback_min_diff = astc::max(min_diff, 1.0f);
 		}
 	}
 
@@ -212,12 +232,49 @@ public:
 	{
 		// Note: m_done_count cannot use an atomic without the mutex; this has a race between the
 		// update here and the wait() for other threads
-		std::unique_lock<std::mutex> lck(m_lock);
-		this->m_done_count += count;
-		if (m_done_count == m_task_count)
+		unsigned int local_count;
+		float local_last_value;
 		{
-			lck.unlock();
-			m_complete.notify_all();
+			std::unique_lock<std::mutex> lck(m_lock);
+			m_done_count += count;
+			local_count = m_done_count;
+			local_last_value = m_callback_last_value;
+
+			if (m_done_count == m_task_count)
+			{
+				// Ensure the progress bar hits 100%
+				if (m_callback)
+				{
+					std::unique_lock<std::mutex> cblck(m_callback_lock);
+					m_callback(100.0f);
+					m_callback_last_value = 100.0f;
+				}
+
+				lck.unlock();
+				m_complete.notify_all();
+			}
+		}
+
+		// Process progress callback if we have one
+		if (m_callback)
+		{
+			// Initial lockless test - have we progressed enough to emit?
+			float num = static_cast<float>(local_count);
+			float den = static_cast<float>(m_task_count);
+			float this_value =  (num / den) * 100.0f;
+			bool report_test = (this_value - local_last_value) > m_callback_min_diff;
+
+			// Recheck under lock, because another thread might report first
+			if (report_test)
+			{
+				std::unique_lock<std::mutex> cblck(m_callback_lock);
+				bool report_retest = (this_value - m_callback_last_value) > m_callback_min_diff;
+				if (report_retest)
+				{
+					m_callback(this_value);
+					m_callback_last_value = this_value;
+				}
+			}
 		}
 	}
 
-- 
cgit v1.2.3