From: Eunki, Hong Date: Tue, 11 Feb 2025 06:54:22 +0000 (+0900) Subject: [NUI](Internal) Implement AsyncImageLoader ImageLoaded signal X-Git-Tag: submit/tizen/20250325.112336~1^2~20 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d36ca055a0abc0502b299e777a887c47c96836d5;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [NUI](Internal) Implement AsyncImageLoader ImageLoaded signal Let we bind AsyncImageLoader's ImageLoaded signal, so we can make it hidden easly in future. Relative dali patches : - https://review.tizen.org/gerrit/c/platform/core/uifw/dali-csharp-binder/+/320850 Signed-off-by: Eunki, Hong --- diff --git a/src/Tizen.NUI/src/internal/Common/AsyncImageLoader.cs b/src/Tizen.NUI/src/internal/Common/AsyncImageLoader.cs index 0a02ef47c..6ae22b6df 100755 --- a/src/Tizen.NUI/src/internal/Common/AsyncImageLoader.cs +++ b/src/Tizen.NUI/src/internal/Common/AsyncImageLoader.cs @@ -15,43 +15,44 @@ * */ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.InteropServices; + namespace Tizen.NUI { + [EditorBrowsable(EditorBrowsableState.Never)] internal class AsyncImageLoader : BaseHandle { + private EventHandler imageLoadedEventHandler; + private EventHandler pixelBufferLoadedEventHandler; + private ImageLoadedSignalType imageLoadedCallback; + private PixelBufferLoadedSignalType pixelBufferLoadedCallback; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void ImageLoadedSignalType(uint loadingTaskId, IntPtr pixelData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void PixelBufferLoadedSignalType(uint loadingTaskId, uint pixelBufferCount, IntPtr pixelBuffer0, IntPtr pixelBuffer1, IntPtr pixelBuffer2); + internal AsyncImageLoader(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn) { } + [EditorBrowsable(EditorBrowsableState.Never)] protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr) { Interop.AsyncImageLoader.DeleteAsyncImageLoader(swigCPtr); } + [EditorBrowsable(EditorBrowsableState.Never)] public AsyncImageLoader() : this(Interop.AsyncImageLoader.New(), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - - } - public AsyncImageLoader(AsyncImageLoader handle) : this(Interop.AsyncImageLoader.NewAsyncImageLoader(AsyncImageLoader.getCPtr(handle)), true) - { - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - } - - public AsyncImageLoader Assign(AsyncImageLoader handle) - { - AsyncImageLoader ret = new AsyncImageLoader(Interop.AsyncImageLoader.Assign(SwigCPtr, AsyncImageLoader.getCPtr(handle)), false); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - - public static AsyncImageLoader DownCast(BaseHandle handle) - { - AsyncImageLoader ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as AsyncImageLoader; - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; } + [EditorBrowsable(EditorBrowsableState.Never)] public uint Load(string url) { uint ret = Interop.AsyncImageLoader.Load(SwigCPtr, url); @@ -59,6 +60,7 @@ namespace Tizen.NUI return ret; } + [EditorBrowsable(EditorBrowsableState.Never)] public uint Load(string url, Uint16Pair dimensions) { uint ret = Interop.AsyncImageLoader.Load(SwigCPtr, url, Uint16Pair.getCPtr(dimensions)); @@ -66,6 +68,7 @@ namespace Tizen.NUI return ret; } + [EditorBrowsable(EditorBrowsableState.Never)] public uint Load(string url, Uint16Pair dimensions, FittingModeType fittingMode, SamplingModeType samplingMode, bool orientationCorrection) { uint ret = Interop.AsyncImageLoader.Load(SwigCPtr, url, Uint16Pair.getCPtr(dimensions), (int)fittingMode, (int)samplingMode, orientationCorrection); @@ -73,6 +76,7 @@ namespace Tizen.NUI return ret; } + [EditorBrowsable(EditorBrowsableState.Never)] public bool Cancel(uint loadingTaskId) { bool ret = Interop.AsyncImageLoader.Cancel(SwigCPtr, loadingTaskId); @@ -80,11 +84,171 @@ namespace Tizen.NUI return ret; } + [EditorBrowsable(EditorBrowsableState.Never)] public void CancelAll() { Interop.AsyncImageLoader.CancelAll(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } + /// + /// You can override it to clean-up your own resources + /// + /// DisposeTypes + [EditorBrowsable(EditorBrowsableState.Never)] + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + + if (type == DisposeTypes.Explicit) + { + //Called by User + //Release your own managed resources here. + //You should release all of your own disposable objects here. + + if (imageLoadedCallback != null) + { + Interop.AsyncImageLoader.ImageLoadedSignalDisconnect(SwigCPtr, imageLoadedCallback.ToHandleRef(this)); + imageLoadedCallback = null; + imageLoadedEventHandler = null; + NDalicPINVOKE.ThrowExceptionIfExists(); + } + + if (pixelBufferLoadedCallback != null) + { + Interop.AsyncImageLoader.PixelBufferLoadedSignalDisconnect(SwigCPtr, pixelBufferLoadedCallback.ToHandleRef(this)); + pixelBufferLoadedCallback = null; + pixelBufferLoadedEventHandler = null; + NDalicPINVOKE.ThrowExceptionIfExists(); + } + } + + //Release your own unmanaged resources here. + //You should not access any managed member here except static instance. + //because the execution order of Finalizes is non-deterministic. + CancelAll(); + + base.Dispose(type); + } + + /// + /// Event when pixel data are loaded. + /// null or empty PixelData if load failed. + /// + /// + /// We cannot use both ImageLoaded and PixelBufferLoaded events. + /// If we use PixelBufferLoaded, ImageLoaded will be ignored. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler ImageLoaded + { + add + { + if (imageLoadedEventHandler == null) + { + imageLoadedCallback = OnImageLoaded; + Interop.AsyncImageLoader.ImageLoadedSignalConnect(SwigCPtr, imageLoadedCallback.ToHandleRef(this)); + NDalicPINVOKE.ThrowExceptionIfExists(); + } + imageLoadedEventHandler += value; + } + + remove + { + imageLoadedEventHandler -= value; + if (imageLoadedEventHandler == null && imageLoadedCallback != null) + { + Interop.AsyncImageLoader.ImageLoadedSignalDisconnect(SwigCPtr, imageLoadedCallback.ToHandleRef(this)); + imageLoadedCallback = null; + NDalicPINVOKE.ThrowExceptionIfExists(); + } + } + } + + /// + /// Event when pixel buffers are loaded. + /// null or empty PixelBuffer list if load failed. + /// + /// + /// We cannot use both ImageLoaded and PixelBufferLoaded events. + /// If we use PixelBufferLoaded, ImageLoaded will be ignored. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler PixelBufferLoaded + { + add + { + if (pixelBufferLoadedEventHandler == null) + { + pixelBufferLoadedCallback = OnPixelBufferLoaded; + Interop.AsyncImageLoader.PixelBufferLoadedSignalConnect(SwigCPtr, pixelBufferLoadedCallback.ToHandleRef(this)); + NDalicPINVOKE.ThrowExceptionIfExists(); + } + pixelBufferLoadedEventHandler += value; + } + + remove + { + pixelBufferLoadedEventHandler -= value; + if (pixelBufferLoadedEventHandler == null && pixelBufferLoadedCallback != null) + { + Interop.AsyncImageLoader.PixelBufferLoadedSignalDisconnect(SwigCPtr, pixelBufferLoadedCallback.ToHandleRef(this)); + pixelBufferLoadedCallback = null; + NDalicPINVOKE.ThrowExceptionIfExists(); + } + } + } + + private void OnImageLoaded(uint loadingTaskId, IntPtr pixelData) + { + ImageLoadedEventArgs e = new ImageLoadedEventArgs(); + e.LoadingTaskId = loadingTaskId; + e.PixelData = pixelData != IntPtr.Zero ? new PixelData(pixelData, false) : null; + + imageLoadedEventHandler?.Invoke(this, e); + } + + private void OnPixelBufferLoaded(uint loadingTaskId, uint pixelBufferListCount, IntPtr pixelBuffer0, IntPtr pixelBuffer1, IntPtr pixelBuffer2) + { + PixelBufferLoadedEventArgs e = new PixelBufferLoadedEventArgs(); + e.LoadingTaskId = loadingTaskId; + e.PixelBuffers = null; + + if (pixelBufferListCount > 0u) + { + e.PixelBuffers = new List(); + if (pixelBufferListCount > 0u) + { + e.PixelBuffers.Add(pixelBuffer0 != IntPtr.Zero ? new PixelBuffer(pixelBuffer0, false) : null); + } + if (pixelBufferListCount > 1u) + { + e.PixelBuffers.Add(pixelBuffer1 != IntPtr.Zero ? new PixelBuffer(pixelBuffer0, false) : null); + } + if (pixelBufferListCount > 2u) + { + e.PixelBuffers.Add(pixelBuffer2 != IntPtr.Zero ? new PixelBuffer(pixelBuffer0, false) : null); + } + } + + pixelBufferLoadedEventHandler?.Invoke(this, e); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public class ImageLoadedEventArgs : EventArgs + { + public uint LoadingTaskId { get; internal set; } + public PixelData PixelData { get; internal set; } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public class PixelBufferLoadedEventArgs : EventArgs + { + public uint LoadingTaskId { get; internal set; } + public List PixelBuffers { get; internal set; } + } } } diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.AsyncImageLoader.cs b/src/Tizen.NUI/src/internal/Interop/Interop.AsyncImageLoader.cs index 16448fc02..908f452bc 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.AsyncImageLoader.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.AsyncImageLoader.cs @@ -25,12 +25,6 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_AsyncImageLoader")] public static extern void DeleteAsyncImageLoader(global::System.Runtime.InteropServices.HandleRef jarg1); - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_AsyncImageLoader__SWIG_1")] - public static extern global::System.IntPtr NewAsyncImageLoader(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_Assign")] - public static extern global::System.IntPtr Assign(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_New")] public static extern global::System.IntPtr New(); @@ -50,8 +44,17 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_CancelAll")] public static extern void CancelAll(global::System.Runtime.InteropServices.HandleRef jarg1); - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_ImageLoadedSignal")] - public static extern global::System.IntPtr ImageLoadedSignal(global::System.Runtime.InteropServices.HandleRef jarg1); + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_ImageLoadedSignal_Connect")] + public static extern void ImageLoadedSignalConnect(global::System.Runtime.InteropServices.HandleRef asyncImageLoader, global::System.Runtime.InteropServices.HandleRef handler); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_ImageLoadedSignal_Disconnect")] + public static extern void ImageLoadedSignalDisconnect(global::System.Runtime.InteropServices.HandleRef asyncImageLoader, global::System.Runtime.InteropServices.HandleRef handler); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_PixelBufferLoadedSignal_Connect")] + public static extern void PixelBufferLoadedSignalConnect(global::System.Runtime.InteropServices.HandleRef asyncImageLoader, global::System.Runtime.InteropServices.HandleRef handler); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_AsyncImageLoader_PixelBufferLoadedSignal_Disconnect")] + public static extern void PixelBufferLoadedSignalDisconnect(global::System.Runtime.InteropServices.HandleRef asyncImageLoader, global::System.Runtime.InteropServices.HandleRef handler); } } } diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/AsyncImageLoaderTest.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/AsyncImageLoaderTest.cs new file mode 100755 index 000000000..bbfff8c48 --- /dev/null +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/AsyncImageLoaderTest.cs @@ -0,0 +1,424 @@ +using System; +using System.Runtime.InteropServices; +using Tizen.NUI.BaseComponents; +using System.Collections.Generic; + +namespace Tizen.NUI.Samples +{ + public class AsyncImageLoaderTest : IExample + { + static readonly string VERTEX_SHADER = + "//@name AsyncImageLoaderTest.vert\n" + + "\n" + + "//@version 100\n" + + "\n" + + "precision highp float;\n" + + "INPUT highp vec2 aPosition;\n" + + "OUTPUT highp vec2 vTexCoord;\n" + + "\n" + + "UNIFORM_BLOCK VertBlock\n" + + "{\n" + + " UNIFORM highp mat4 uMvpMatrix;\n" + + " UNIFORM highp vec3 uSize;\n" + + "};\n" + + "void main()\n" + + "{\n" + + " vec4 pos = vec4(aPosition, 0.0, 1.0) * vec4(uSize, 1.0);\n" + + " vTexCoord = aPosition + vec2(0.5);\n" + + " gl_Position = uMvpMatrix * pos;\n" + + "}\n"; + + static readonly string FRAGMENT_SHADER = + "//@name AsyncImageLoaderTest.frag\n" + + "\n" + + "//@version 100\n" + + "\n" + + "precision highp float;\n" + + "\n" + + "INPUT highp vec2 vTexCoord;\n" + + "UNIFORM sampler2D sTexture;\n" + + "UNIFORM_BLOCK FragBlock\n" + + "{\n" + + " UNIFORM lowp vec4 uColor;\n" + + "};\n" + + "\n" + + "void main()\n" + + "{\n" + + " gl_FragColor = TEXTURE( sTexture, vTexCoord ) * uColor;\n" + + "}\n"; + + struct SimpleQuadVertex + { + public UIVector2 position; + } + + private PropertyBuffer CreateQuadPropertyBuffer() + { + /* Create Property buffer */ + PropertyMap vertexFormat = new PropertyMap(); + vertexFormat.Add("aPosition", (int)PropertyType.Vector2); + + PropertyBuffer vertexBuffer = new PropertyBuffer(vertexFormat); + + SimpleQuadVertex vertex1 = new SimpleQuadVertex(); + SimpleQuadVertex vertex2 = new SimpleQuadVertex(); + SimpleQuadVertex vertex3 = new SimpleQuadVertex(); + SimpleQuadVertex vertex4 = new SimpleQuadVertex(); + vertex1.position = new UIVector2(-0.5f, -0.5f); + vertex2.position = new UIVector2(-0.5f, 0.5f); + vertex3.position = new UIVector2(0.5f, -0.5f); + vertex4.position = new UIVector2(0.5f, 0.5f); + + SimpleQuadVertex[] texturedQuadVertexData = new SimpleQuadVertex[4] { vertex1, vertex2, vertex3, vertex4 }; + + int size = Marshal.SizeOf(vertex1); + IntPtr pA = Marshal.AllocHGlobal(checked(size * texturedQuadVertexData.Length)); + + try + { + for (int i = 0; i < texturedQuadVertexData.Length; i++) + { + Marshal.StructureToPtr(texturedQuadVertexData[i], pA + i * size, true); + } + + vertexBuffer.SetData(pA, (uint)texturedQuadVertexData.Length); + } + catch(Exception e) + { + Tizen.Log.Error("NUI", "Exception in CreateQuadPropertyBuffer : " + e.Message); + } + finally + { + // Free AllocHGlobal memory after call PropertyBuffer.SetData() + Marshal.FreeHGlobal(pA); + } + + vertexFormat.Dispose(); + + return vertexBuffer; + } + + private Window win; + private View root; + + private static uint numberOfLoaderType = 3u; + private static uint numberOfImagesPerEachType = 12u; + private static uint totalSubViewCounts = numberOfLoaderType * numberOfImagesPerEachType; + + // Per each view + private View[] subView = new View[totalSubViewCounts]; + private TextureSet[] subViewTextureSet = new TextureSet[totalSubViewCounts]; + private uint[] subViewLoadId = new uint[totalSubViewCounts]; + + // Per each image loader + private uint[] subViewUrlIndex = new uint[numberOfLoaderType]; + private AsyncImageLoader[] imageLoader = new AsyncImageLoader[numberOfLoaderType]; + + private static uint InvalidLoadId = 0u; + + private static string DEMO_IMAGE_DIR = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "images/"; + + private static readonly string[] ImageUrlList = { + DEMO_IMAGE_DIR + "Dali/ContactCard/gallery-small-2.jpg", + DEMO_IMAGE_DIR + "Dali/ContactCard/gallery-small-3.jpg", + DEMO_IMAGE_DIR + "Dali/ContactCard/contact-cards-mask.png", /// RGBA8888 + DEMO_IMAGE_DIR + "AGIF/dali-logo-anim.gif", /// Animated image, but will be loaded as single frame. + "invalid.jpg", /// Invalid image + }; + + public void Activate() + { + win = NUIApplication.GetDefaultWindow(); + win.KeyEvent += WindowKeyEvent; + + root = new View() + { + Name = "root", + WidthResizePolicy = ResizePolicyType.FillToParent, + HeightResizePolicy = ResizePolicyType.FillToParent, + }; + win.Add(root); + + AddViews(); + var infoLabel = new TextLabel() + { + Text = "1'st : ImageLoaded event.\n2'nd : PixelBufferLoaded event.\n3'rd : PixelBufferLoaded event and change it's own logic.\n\nPress 1~3 key to load each images.\nPress 0 key to load whole images", + MultiLine = true, + }; + root.Add(infoLabel); + + for(uint i = 0u; i < numberOfLoaderType; ++i) + { + imageLoader[i] = new AsyncImageLoader(); + } + + imageLoader[0].ImageLoaded += OnImageLoaded; + imageLoader[1].PixelBufferLoaded += OnPixelBufferLoaded; + imageLoader[2].PixelBufferLoaded += OnPixelBufferLoadedWithCustom; + } + + public void Deactivate() + { + for(uint i = 0u; i < numberOfLoaderType; ++i) + { + imageLoader[i]?.Dispose(); + } + root?.Unparent(); + root?.Dispose(); + + win.KeyEvent -= WindowKeyEvent; + } + + private void WindowKeyEvent(object sender, Window.KeyEventArgs e) + { + if (e.Key.State == Key.StateType.Down) + { + try + { + if (e.Key.KeyPressedName == "0" || e.Key.KeyPressedName == "1") + { + RequestLoad(0); + } + if (e.Key.KeyPressedName == "0" || e.Key.KeyPressedName == "2") + { + RequestLoad(1); + } + if (e.Key.KeyPressedName == "0" || e.Key.KeyPressedName == "3") + { + RequestLoad(2); + } + } + catch(Exception ex) + { + Tizen.Log.Error("NUI", "Exception in RequestLoad : " + ex.Message); + } + } + } + + private void AddViews() + { + for (uint i = 0u; i < numberOfLoaderType; ++i) + { + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + // View area is red, and additional renderer area is yellow. + View view = new View() + { + Name = $"subView{i}x{j}", + BackgroundColor = Color.Red, + SizeWidth = 100.0f, + SizeHeight = 100.0f, + PositionX = j * 100.0f, + PositionY = i * 250.0f + 50.0f, + }; + + var renderer = GenerateRenderer(); + + view.AddRenderer(renderer); + root.Add(view); + + uint viewIndex = i * numberOfImagesPerEachType + j; + + subView[viewIndex] = view; + subViewTextureSet[viewIndex] = renderer.GetTextures(); + subViewLoadId[viewIndex] = InvalidLoadId; + } + subViewUrlIndex[i] = (uint)(ImageUrlList.Length - 1); + } + } + + private void RequestLoad(uint loaderIndex) + { + if (loaderIndex >= 3) + { + throw new ArgumentException($"Invalid subViewIndex comes! {loaderIndex}"); + } + + if (imageLoader[loaderIndex] == null) + { + Tizen.Log.Info("NUITest", $"Image loader Disposed!\n"); + return; + } + + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + uint viewIndex = loaderIndex * numberOfImagesPerEachType + j; + if (subViewLoadId[viewIndex] != InvalidLoadId) + { + Tizen.Log.Info("NUITest", $"Cancel {viewIndex}'th loadId {subViewLoadId[viewIndex]}\n"); + imageLoader[loaderIndex].Cancel(subViewLoadId[viewIndex]); + subViewLoadId[viewIndex] = InvalidLoadId; + } + } + + subViewUrlIndex[loaderIndex] = (uint)((subViewUrlIndex[loaderIndex] + 1u) % ImageUrlList.Length); + + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + uint viewIndex = loaderIndex * numberOfImagesPerEachType + j; + subViewLoadId[viewIndex] = imageLoader[loaderIndex].Load(ImageUrlList[subViewUrlIndex[loaderIndex]]); + Tizen.Log.Info("NUITest", $"Load {viewIndex}'th loadId {subViewLoadId[viewIndex]}\n"); + } + } + + private void OnImageLoaded(object o, AsyncImageLoader.ImageLoadedEventArgs e) + { + uint viewIndex = 0u; + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + viewIndex = 0u * numberOfImagesPerEachType + j; + if (subViewLoadId[viewIndex] == e.LoadingTaskId) + { + break; + } + } + + if (subViewLoadId[viewIndex] != e.LoadingTaskId) + { + // Should never comes here! + Tizen.Log.Error("NUITest", $"{viewIndex}'th loadId not matched with callback input {e.LoadingTaskId}!!\n"); + return; + } + if (e.PixelData == null) + { + Tizen.Log.Info("NUITest", $"Load Fail {viewIndex}'th loadId {subViewLoadId[viewIndex]}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + return; + } + + var width = e.PixelData.GetWidth(); + var height = e.PixelData.GetHeight(); + var pixelFormat = e.PixelData.GetPixelFormat(); + Tizen.Log.Info("NUITest", $"Load Complete {viewIndex}'th loadId {subViewLoadId[viewIndex]} : {width}x{height} with format {pixelFormat}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + + Texture texture = new Texture(TextureType.TEXTURE_2D, pixelFormat, width, height); + texture.Upload(e.PixelData); + + subViewTextureSet[viewIndex].SetTexture(0u, texture); + } + + private void OnPixelBufferLoaded(object o, AsyncImageLoader.PixelBufferLoadedEventArgs e) + { + uint viewIndex = 0u; + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + viewIndex = 1u * numberOfImagesPerEachType + j; + if (subViewLoadId[viewIndex] == e.LoadingTaskId) + { + break; + } + } + + if (subViewLoadId[viewIndex] != e.LoadingTaskId) + { + // Should never comes here! + Tizen.Log.Error("NUITest", $"{viewIndex}'th loadId {subViewLoadId[viewIndex]} not matched with callback input {e.LoadingTaskId}!!\n"); + return; + } + if (e.PixelBuffers == null || e.PixelBuffers.Count == 0 || e.PixelBuffers[0] == null) + { + Tizen.Log.Info("NUITest", $"Load Fail {viewIndex}'th loadId {subViewLoadId[viewIndex]}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + return; + } + + PixelData pixelData = PixelBuffer.Convert(e.PixelBuffers[0]); + + var width = pixelData.GetWidth(); + var height = pixelData.GetHeight(); + var pixelFormat = pixelData.GetPixelFormat(); + Tizen.Log.Info("NUITest", $"Complete {viewIndex}'th loadId {subViewLoadId[viewIndex]} : {width}x{height} with format {pixelFormat}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + + Texture texture = new Texture(TextureType.TEXTURE_2D, pixelFormat, width, height); + texture.Upload(pixelData); + + subViewTextureSet[viewIndex].SetTexture(0u, texture); + } + + private void OnPixelBufferLoadedWithCustom(object o, AsyncImageLoader.PixelBufferLoadedEventArgs e) + { + uint viewIndex = 0u; + for (uint j = 0u; j < numberOfImagesPerEachType; ++j) + { + viewIndex = 2u * numberOfImagesPerEachType + j; + if (subViewLoadId[viewIndex] == e.LoadingTaskId) + { + break; + } + } + + if (subViewLoadId[viewIndex] != e.LoadingTaskId) + { + // Should never comes here! + Tizen.Log.Error("NUITest", $"{viewIndex}'th loadId {subViewLoadId[viewIndex]} not matched with callback input {e.LoadingTaskId}!!\n"); + return; + } + if (e.PixelBuffers == null || e.PixelBuffers.Count == 0 || e.PixelBuffers[0] == null) + { + Tizen.Log.Info("NUITest", $"Load Fail {viewIndex}'th loadId {subViewLoadId[viewIndex]}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + return; + } + + PixelBuffer pixelBuffer = e.PixelBuffers[0]; + + // Do something custom actions for this pixelBuffer. + pixelBuffer.Rotate(new Degree((float)viewIndex * 20.0f)); + + PixelData pixelData = PixelBuffer.Convert(pixelBuffer); + + var width = pixelData.GetWidth(); + var height = pixelData.GetHeight(); + var pixelFormat = pixelData.GetPixelFormat(); + Tizen.Log.Info("NUITest", $"Complete {viewIndex}'th loadId {subViewLoadId[viewIndex]} : {width}x{height} with format {pixelFormat}\n"); + + subViewLoadId[viewIndex] = InvalidLoadId; + + Texture texture = new Texture(TextureType.TEXTURE_2D, pixelFormat, width, height); + texture.Upload(pixelData); + + subViewTextureSet[viewIndex].SetTexture(0u, texture); + } + + private Geometry GenerateGeometry() + { + using PropertyBuffer vertexBuffer = CreateQuadPropertyBuffer(); + Geometry geometry = new Geometry(); + geometry.AddVertexBuffer(vertexBuffer); + geometry.SetType(Geometry.Type.TRIANGLE_STRIP); + + return geometry; + } + + private Shader GenerateShader() + { + Shader shader = new Shader(VERTEX_SHADER, FRAGMENT_SHADER, "RendererUpdateAreaTest"); + return shader; + } + + private Renderer GenerateRenderer() + { + Renderer renderer = new Renderer(); + Geometry geometry = GenerateGeometry(); + Shader shader = GenerateShader(); + TextureSet textureSet = new TextureSet(); + + // Set some invalid texture so we can ignore rendering. + Texture texture = new Texture(TextureType.TEXTURE_2D, PixelFormat.RGBA8888, 1u, 1u); + textureSet.SetTexture(0u, texture); + + renderer.SetGeometry(geometry); + renderer.SetShader(shader); + renderer.SetTextures(textureSet); + + return renderer; + } + } +}