示例#1
0
        /// <summary>
        /// Updates this audio component. Always runs on the audio thread.
        /// </summary>
        public void Update()
        {
            ThreadSafety.EnsureNotUpdateThread();

            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not update disposed audio components.");
            }

            FrameStatistics.Add(StatisticsCounterType.TasksRun, PendingActions.Count);
            FrameStatistics.Increment(StatisticsCounterType.Components);

            while (!IsDisposed && PendingActions.TryDequeue(out Task task))
            {
                task.RunSynchronously();
            }

            if (!IsDisposed)
            {
                UpdateState();
            }

            UpdateChildren();
        }
示例#2
0
        public void CreateIndex(string name, IIndex index)
        {
            CBDebug.MustNotBeNull(Log.To.Database, Tag, nameof(name), name);
            CBDebug.MustNotBeNull(Log.To.Database, Tag, nameof(index), index);

            ThreadSafety.DoLocked(() =>
            {
                CheckOpen();
                var concreteIndex = Misc.TryCast <IIndex, QueryIndex>(index);
                var jsonObj       = concreteIndex.ToJSON();
                var json          = JsonConvert.SerializeObject(jsonObj);
                LiteCoreBridge.Check(err =>
                {
                    var internalOpts = concreteIndex.Options;

                    // For some reason a "using" statement here causes a compiler error
                    try {
                        return(Native.c4db_createIndex(c4db, name, json, concreteIndex.IndexType, &internalOpts, err));
                    } finally {
                        internalOpts.Dispose();
                    }
                });
            });
        }
 internal DictionaryObject(MDict dict, bool isMutable)
 {
     _dict.InitAsCopyOf(dict, isMutable);
     _threadSafety = SetupThreadSafety();
 }
 internal DictionaryObject(MValue mv, MCollection parent)
 {
     _dict.InitInSlot(mv, parent);
     _threadSafety = SetupThreadSafety();
 }
 internal DictionaryObject()
 {
     _threadSafety = SetupThreadSafety();
 }
示例#6
0
 /// <summary>
 /// Constructs a replicator based on the given <see cref="ReplicatorConfiguration"/>
 /// </summary>
 /// <param name="config">The configuration to use to create the replicator</param>
 public Replicator([NotNull] ReplicatorConfiguration config)
 {
     Config = CBDebug.MustNotBeNull(Log.To.Sync, Tag, nameof(config), config).Freeze();
     _databaseThreadSafety = Config.Database.ThreadSafety;
 }
示例#7
0
        /// <summary>
        /// Invalidates draw matrix and autosize caches.
        /// </summary>
        /// <returns>If the invalidate was actually necessary.</returns>
        public virtual bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
        {
            if (invalidation == Invalidation.None)
            {
                return(false);
            }

            ThreadSafety.EnsureUpdateThread();

            OnInvalidate?.Invoke();

            if (shallPropagate && Parent != null && source != Parent)
            {
                Parent.Invalidate(Parent.InvalidationEffectByChildren(invalidation), this, false);
            }

            bool alreadyInvalidated = true;

            if ((invalidation & Invalidation.SizeInParentSpace) > 0)
            {
                alreadyInvalidated &= !boundingSizeBacking.Invalidate();
            }

            // Either ScreenSize OR ScreenPosition
            if ((invalidation & Invalidation.ScreenSpaceQuad) > 0)
            {
                alreadyInvalidated &= !screenSpaceDrawQuadBacking.Invalidate();
            }

            // Either ScreenSize OR ScreenPosition OR Colour
            if ((invalidation & Invalidation.DrawInfo) > 0)
            {
                alreadyInvalidated &= !drawInfoBacking.Invalidate();
            }

            if ((invalidation & Invalidation.Visibility) > 0)
            {
                alreadyInvalidated &= !isVisibleBacking.Invalidate();
            }

            if (alreadyInvalidated || !shallPropagate)
            {
                return(!alreadyInvalidated);
            }

            if (children != null)
            {
                foreach (var c in children)
                {
                    Debug.Assert(c != source);

                    Invalidation childInvalidation = invalidation;
                    //if (c.SizeMode == InheritMode.None)
                    childInvalidation = childInvalidation & ~Invalidation.SizeInParentSpace;

                    c.Invalidate(childInvalidation, this);
                }
            }

            return(!alreadyInvalidated);
        }
示例#8
0
        public Docs LoadDocs(XElement dElement, string filePath)
        {
            dElement = TransformDocs(dElement);
            if (dElement == null)
            {
                return(null);
            }

            var    remarks      = dElement.Element("remarks");
            string remarksText  = NormalizeDocsElement(remarks, true);
            string examplesText = null;

            if (remarksText != null)
            {
                if (remarksText.Contains("</format>"))
                {
                    Console.WriteLine(filePath);
                    Console.WriteLine(remarksText);
                }
                remarksText = remarksText.Replace("## Remarks", "").Trim();
                if (remarksText.Contains("## Examples"))
                {
                    var pos = remarksText.IndexOf("## Examples");
                    examplesText = remarksText.Substring(pos).Replace("## Examples", "").Trim();
                    remarksText  = remarksText.Substring(0, pos).Trim();
                }
            }

            remarksText = DowngradeMarkdownHeaders(remarksText);

            var examples = dElement.Elements("example");

            if (examples != null && examples.Count() > 0)
            {
                examplesText  = string.IsNullOrEmpty(examplesText) ? "" : examplesText + "\n\n";
                examplesText += string.Join("\n\n", examples.Select(example => NormalizeDocsElement(example)));
            }

            List <RelatedTag> related = null;
            var relatedElements       = dElement.Elements("related")?.ToList();

            if (relatedElements?.Count > 0)
            {
                related = LoadRelated(relatedElements);
            }

            Dictionary <string, string> additionalNotes = null;
            var blocks = dElement.Elements("block")?.Where(p => !string.IsNullOrEmpty(p.Attribute("type")?.Value)).ToList();

            if (blocks != null && blocks.Count > 0)
            {
                additionalNotes = new Dictionary <string, string>();
                foreach (var block in blocks)
                {
                    var valElement = block;
                    var elements   = block.Elements().ToArray();
                    if (elements?.Length == 1 && elements[0].Name.LocalName == "p")
                    {
                        valElement = elements[0];
                    }
                    additionalNotes[block.Attribute("type").Value] = NormalizeDocsElement(GetInnerXml(valElement));
                }
            }

            string       threadSafetyContent = null;
            ThreadSafety threadSafety        = null;
            var          threadSafeEle       = dElement.Element("threadsafe");

            if (threadSafeEle != null)
            {
                threadSafetyContent = NormalizeDocsElement(GetInnerXml(threadSafeEle));
                var supportedAttr = threadSafeEle.Attribute("supported");
                threadSafety = new ThreadSafety()
                {
                    CustomContent = threadSafetyContent,
                    Supported     = supportedAttr?.Value?.Equals("true", StringComparison.OrdinalIgnoreCase),
                    MemberScope   = threadSafeEle.Attribute("memberScope")?.Value
                };
            }

            var        inheritdocEle = dElement.Element("inheritdoc");
            InheritDoc inheritDoc    = null;

            if (inheritdocEle != null)
            {
                inheritDoc = new InheritDoc();

                // TODO: other attributes parse
            }

            return(new Docs()
            {
                Summary = NormalizeDocsElement(dElement.Element("summary")),
                Remarks = remarksText,
                Examples = examplesText,
                AltMemberCommentIds = MergeAltmemberAndSeealsoToAltMemberCommentsIds(dElement),//dElement.Elements("altmember")?.Select(alt => alt.Attribute("cref").Value).ToList(),
                Related = related,
                Exceptions = dElement.Elements("exception")?.Select(el => GetTypedContent(el, filePath)).ToList(),
                Permissions = dElement.Elements("permission")?.Select(el => GetTypedContent(el, filePath)).ToList(),
                Parameters = dElement.Elements("param")?.Where(p => !string.IsNullOrEmpty(p.Attribute("name").Value)).ToDictionary(p => p.Attribute("name").Value, p => NormalizeDocsElement(p)),
                TypeParameters = dElement.Elements("typeparam")?.Where(p => !string.IsNullOrEmpty(p.Attribute("name").Value)).ToDictionary(p => p.Attribute("name").Value, p => NormalizeDocsElement(GetInnerXml(p))),
                AdditionalNotes = additionalNotes,
                Returns = NormalizeDocsElement(dElement.Element("returns")), //<value> will be transformed to <returns> by xslt in advance
                ThreadSafety = threadSafetyContent,
                ThreadSafetyInfo = threadSafety,
                Since = NormalizeDocsElement(dElement.Element("since")?.Value),
                AltCompliant = dElement.Element("altCompliant")?.Attribute("cref")?.Value,
                InternalOnly = dElement.Element("forInternalUseOnly") != null,
                Inheritdoc = inheritDoc
            });
        }
示例#9
0
 internal ArrayObject([NotNull] ArrayObject original, bool mutable)
     : this(original._array, mutable)
 {
     _threadSafety = SetupThreadSafety();
 }
示例#10
0
        internal void ResolveConflict([NotNull] string docID, [NotNull] IConflictResolver resolver)
        {
            Debug.Assert(docID != null);

            Document doc = null, otherDoc = null, baseDoc = null;
            var      inConflict = true;

            while (inConflict)
            {
                ThreadSafety.DoLocked(() =>
                {
                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(_c4db, err));
                    try {
                        doc = new Document(this, docID);
                        if (!doc.Exists)
                        {
                            doc.Dispose();
                            return;
                        }

                        otherDoc = new Document(this, docID);
                        if (!otherDoc.Exists)
                        {
                            doc.Dispose();
                            otherDoc.Dispose();
                            return;
                        }

                        otherDoc.SelectConflictingRevision();
                        baseDoc = new Document(this, docID);
                        if (!baseDoc.SelectCommonAncestor(doc, otherDoc) || baseDoc.ToDictionary() == null)
                        {
                            baseDoc.Dispose();
                            baseDoc = null;
                        }

                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(_c4db, true, err));
                    } catch (Exception) {
                        doc?.Dispose();
                        otherDoc?.Dispose();
                        baseDoc?.Dispose();
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(_c4db, false, err));
                    }
                });

                var conflict = new Conflict(doc, otherDoc, baseDoc);
                var logID    = new SecureLogString(doc.Id, LogMessageSensitivity.PotentiallyInsecure);
                Log.To.Database.I(Tag, $"Resolving doc '{logID}' with {resolver.GetType().Name} (mine={doc.RevID}, theirs={otherDoc.RevID}, base={baseDoc?.RevID})");
                Document resolved = null;
                try {
                    resolved = resolver.Resolve(conflict);
                    if (resolved == null)
                    {
                        throw new LiteCoreException(new C4Error(C4ErrorCode.Conflict));
                    }

                    SaveResolvedDocument(resolved, conflict);
                    inConflict = false;
                } catch (LiteCoreException e) {
                    if (e.Error.domain == C4ErrorDomain.LiteCoreDomain && e.Error.code == (int)C4ErrorCode.Conflict)
                    {
                        continue;
                    }

                    throw;
                } finally {
                    resolved?.Dispose();
                    if (resolved != doc)
                    {
                        doc?.Dispose();
                    }

                    if (resolved != otherDoc)
                    {
                        otherDoc?.Dispose();
                    }

                    if (resolved != baseDoc)
                    {
                        baseDoc?.Dispose();
                    }
                }
            }
        }
示例#11
0
 public Document GetDocument(string id)
 {
     CBDebug.MustNotBeNull(Log.To.Database, Tag, nameof(id), id);
     return(ThreadSafety.DoLocked(() => GetDocumentInternal(id)));
 }
示例#12
0
        private void Save([NotNull] Document doc, C4Document **outDoc, C4Document *baseDoc, bool deletion)
        {
            var revFlags = (C4RevisionFlags)0;

            if (deletion)
            {
                revFlags = C4RevisionFlags.Deleted;
            }

            byte[] body = null;
            if (!deletion && !doc.IsEmpty)
            {
                body = doc.Encode();
                var root = Native.FLValue_FromTrustedData(body);
                if (root == null)
                {
                    Log.To.Database.E(Tag, "Failed to encode document body properly.  Aborting save of document!");
                    return;
                }

                var rootDict = Native.FLValue_AsDict(root);
                if (rootDict == null)
                {
                    Log.To.Database.E(Tag, "Failed to encode document body properly.  Aborting save of document!");
                    return;
                }

                ThreadSafety.DoLocked(() =>
                {
                    if (Native.c4doc_dictContainsBlobs(rootDict, SharedStrings.SharedKeys))
                    {
                        revFlags |= C4RevisionFlags.HasAttachments;
                    }
                });
            }
            else if (doc.IsEmpty)
            {
                FLEncoder *encoder = SharedEncoder;
                Native.FLEncoder_BeginDict(encoder, 0);
                Native.FLEncoder_EndDict(encoder);
                body = Native.FLEncoder_Finish(encoder, null);
                Native.FLEncoder_Reset(encoder);
            }

            var rawDoc = baseDoc != null ? baseDoc :
                         doc.c4Doc?.HasValue == true ? doc.c4Doc.RawDoc : null;

            if (rawDoc != null)
            {
                doc.ThreadSafety.DoLocked(() =>
                {
                    ThreadSafety.DoLocked(() =>
                    {
                        *outDoc = (C4Document *)NativeHandler.Create()
                                  .AllowError((int)C4ErrorCode.Conflict, C4ErrorDomain.LiteCoreDomain).Execute(
                            err => Native.c4doc_update(rawDoc, body, revFlags, err));
                    });
                });
            }
            else
            {
                ThreadSafety.DoLocked(() =>
                {
                    *outDoc = (C4Document *)NativeHandler.Create()
                              .AllowError((int)C4ErrorCode.Conflict, C4ErrorDomain.LiteCoreDomain).Execute(
                        err => Native.c4doc_create(_c4db, doc.Id, body, revFlags, err));
                });
            }
        }
示例#13
0
        private Document Save([NotNull] Document document, bool deletion)
        {
            if (document.IsInvalidated)
            {
                throw new CouchbaseLiteException(StatusCode.NotAllowed, "Cannot save or delete a MutableDocument that has already been used to save or delete");
            }

            if (deletion && document.RevID == null)
            {
                throw new CouchbaseLiteException(StatusCode.NotAllowed, "Cannot delete a document that has not yet been saved");
            }

            var         docID = document.Id;
            var         doc = document;
            Document    baseDoc = null, otherDoc = null;
            C4Document *newDoc = null;
            Document    retVal = null;

            while (true)
            {
                var resolve = false;
                retVal = ThreadSafety.DoLocked(() =>
                {
                    VerifyDB(doc);
                    LiteCoreBridge.Check(err => Native.c4db_beginTransaction(_c4db, err));
                    try {
                        if (deletion)
                        {
                            // Check for no-op case if the document does not exist
                            var curDoc = (C4Document *)NativeHandler.Create().AllowError(new C4Error(C4ErrorCode.NotFound))
                                         .Execute(err => Native.c4doc_get(_c4db, docID, true, err));
                            if (curDoc == null)
                            {
                                (document as MutableDocument)?.MarkAsInvalidated();
                                return(null);
                            }

                            Native.c4doc_free(curDoc);
                        }

                        var newDocOther = newDoc;
                        Save(doc, &newDocOther, baseDoc?.c4Doc?.HasValue == true ? baseDoc.c4Doc.RawDoc : null, deletion);
                        if (newDocOther != null)
                        {
                            // Save succeeded, so commit
                            newDoc = newDocOther;
                            LiteCoreBridge.Check(err =>
                            {
                                var success = Native.c4db_endTransaction(_c4db, true, err);
                                if (!success)
                                {
                                    Native.c4doc_free(newDoc);
                                }

                                return(success);
                            });

                            (document as MutableDocument)?.MarkAsInvalidated();
                            baseDoc?.Dispose();
                            return(new Document(this, docID, new C4DocumentWrapper(newDoc)));
                        }

                        // There was a conflict
                        if (deletion && !doc.IsDeleted)
                        {
                            var deletedDoc = doc.ToMutable();
                            deletedDoc.MarkAsDeleted();
                            doc = deletedDoc;
                        }

                        if (doc.c4Doc != null)
                        {
                            baseDoc = new Document(this, docID, doc.c4Doc.Retain <C4DocumentWrapper>());
                        }

                        otherDoc = new Document(this, docID);
                        if (!otherDoc.Exists)
                        {
                            LiteCoreBridge.Check(err => Native.c4db_endTransaction(_c4db, false, err));
                            return(null);
                        }
                    } catch (Exception) {
                        baseDoc?.Dispose();
                        otherDoc?.Dispose();
                        LiteCoreBridge.Check(err => Native.c4db_endTransaction(_c4db, false, err));
                        throw;
                    }

                    resolve = true;
                    LiteCoreBridge.Check(err => Native.c4db_endTransaction(_c4db, false, err));
                    return(null);
                });

                if (!resolve)
                {
                    return(retVal);
                }

                // Resolve Conflict
                Document resolved = null;
                try {
                    var resolver = Config.ConflictResolver;
                    var conflict = new Conflict(doc, otherDoc, baseDoc);
                    resolved = resolver.Resolve(conflict);
                    if (resolved == null)
                    {
                        throw new LiteCoreException(new C4Error(C4ErrorCode.Conflict));
                    }
                } finally {
                    baseDoc?.Dispose();
                    if (!ReferenceEquals(resolved, otherDoc))
                    {
                        otherDoc?.Dispose();
                    }
                }

                retVal = ThreadSafety.DoLocked(() =>
                {
                    var current = new Document(this, docID);
                    if (resolved.RevID == current.RevID)
                    {
                        (document as MutableDocument)?.MarkAsInvalidated();
                        current.Dispose();
                        return(resolved); // Same as current
                    }

                    // For saving
                    doc      = resolved;
                    baseDoc  = current;
                    deletion = resolved.IsDeleted;
                    return(null);
                });

                if (retVal != null)
                {
                    return(retVal);
                }
            }
        }
示例#14
0
 internal DatabaseSource([NotNull] Database database, [NotNull] ThreadSafety threadSafety) : base(database, threadSafety)
 {
     Debug.Assert(database != null);
 }
 public DatabaseSource(Database database, [NotNull] ThreadSafety threadSafety) : base(database, threadSafety)
 {
 }
示例#16
0
 internal ArrayObject()
 {
     _threadSafety = SetupThreadSafety();
 }
示例#17
0
 internal ArrayObject([NotNull] FleeceMutableArray array, bool isMutable)
 {
     _array.InitAsCopyOf(array, isMutable);
     _threadSafety = SetupThreadSafety();
 }
示例#18
0
        internal override bool Upload()
        {
            // We should never run raw OGL calls on another thread than the main thread due to race conditions.
            ThreadSafety.EnsureDrawThread();

            if (isDisposed)
            {
                return(false);
            }

            IntPtr        dataPointer;
            GCHandle?     h0;
            TextureUpload upload;
            bool          didUpload = false;

            while (uploadQueue.TryDequeue(out upload))
            {
                if (upload.Data.Length == 0)
                {
                    h0          = null;
                    dataPointer = IntPtr.Zero;
                }
                else
                {
                    h0          = GCHandle.Alloc(upload.Data, GCHandleType.Pinned);
                    dataPointer = h0.Value.AddrOfPinnedObject();
                    didUpload   = true;
                }

                try
                {
                    // Do we need to generate a new texture?
                    if (textureId <= 0 || internalWidth < width || internalHeight < height)
                    {
                        internalWidth  = width;
                        internalHeight = height;

                        // We only need to generate a new texture if we don't have one already. Otherwise just re-use the current one.
                        if (textureId <= 0)
                        {
                            int[] textures = new int[1];
                            GL.GenTextures(1, textures);

                            textureId = textures[0];

                            GLWrapper.BindTexture(textureId);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);

                            updateWrapMode();
                        }
                        else
                        {
                            GLWrapper.BindTexture(textureId);
                        }

                        if (width == upload.Bounds.Width && height == upload.Bounds.Height || dataPointer == IntPtr.Zero)
                        {
                            GL.TexImage2D(TextureTarget2d.Texture2D, upload.Level, TextureComponentCount.Rgba, width, height, 0, upload.Format, PixelType.UnsignedByte, dataPointer);
                        }
                        else
                        {
                            initializeLevel(upload.Level, width, height);

                            GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X, upload.Bounds.Y, upload.Bounds.Width, upload.Bounds.Height, upload.Format, PixelType.UnsignedByte, dataPointer);
                        }
                    }
                    // Just update content of the current texture
                    else if (dataPointer != IntPtr.Zero)
                    {
                        GLWrapper.BindTexture(textureId);

                        if (!manualMipmaps && upload.Level > 0)
                        {
                            //allocate mipmap levels
                            int level = 1;
                            int d     = 2;

                            while (width / d > 0)
                            {
                                initializeLevel(level, width / d, height / d);
                                level++;
                                d *= 2;
                            }

                            manualMipmaps = true;
                        }

                        int div = (int)Math.Pow(2, upload.Level);

                        GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X / div, upload.Bounds.Y / div, upload.Bounds.Width / div, upload.Bounds.Height / div, upload.Format, PixelType.UnsignedByte, dataPointer);
                    }
                }
                finally
                {
                    h0?.Free();
                    upload?.Dispose();
                }
            }

            if (didUpload && !manualMipmaps)
            {
                GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest);
                GL.GenerateMipmap(TextureTarget.Texture2D);
            }

            return(didUpload);
        }
示例#19
0
 internal ArrayObject(MValue mv, MCollection parent)
 {
     _array.InitInSlot(mv, parent);
     _threadSafety = SetupThreadSafety();
 }
示例#20
0
 // Does the command mutate global state?
 internal static bool CommandDefined(TpmCc command)
 {
     return(ThreadSafety.ContainsKey(command));
 }
示例#21
0
        internal override bool Upload()
        {
            // We should never run raw OGL calls on another thread than the main thread due to race conditions.
            ThreadSafety.EnsureDrawThread();

            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not upload data to a disposed texture.");
            }

            bool didUpload = false;

            while (uploadQueue.TryDequeue(out TextureUpload upload))
            {
                IntPtr   dataPointer;
                GCHandle?h0;

                if (upload.Data.Length == 0)
                {
                    h0          = null;
                    dataPointer = IntPtr.Zero;
                }
                else
                {
                    h0          = GCHandle.Alloc(upload.Data, GCHandleType.Pinned);
                    dataPointer = h0.Value.AddrOfPinnedObject();
                    didUpload   = true;
                }

                try
                {
                    // Do we need to generate a new texture?
                    if (textureId <= 0 || internalWidth != width || internalHeight != height)
                    {
                        internalWidth  = width;
                        internalHeight = height;

                        // We only need to generate a new texture if we don't have one already. Otherwise just re-use the current one.
                        if (textureId <= 0)
                        {
                            int[] textures = new int[1];
                            GL.GenTextures(1, textures);

                            textureId = textures[0];

                            GLWrapper.BindTexture(this);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
                                            (int)(manualMipmaps ? filteringMode : (filteringMode == All.Linear ? All.LinearMipmapLinear : All.Nearest)));
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)filteringMode);

                            // 33085 is GL_TEXTURE_MAX_LEVEL, which is not available within TextureParameterName.
                            // It controls the amount of mipmap levels generated by GL.GenerateMipmap later on.
                            GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)33085, MAX_MIPMAP_LEVELS);

                            updateWrapMode();
                        }
                        else
                        {
                            GLWrapper.BindTexture(this);
                        }

                        if (width == upload.Bounds.Width && height == upload.Bounds.Height || dataPointer == IntPtr.Zero)
                        {
                            GL.TexImage2D(TextureTarget2d.Texture2D, upload.Level, TextureComponentCount.Srgb8Alpha8, width, height, 0, upload.Format, PixelType.UnsignedByte, dataPointer);
                        }
                        else
                        {
                            initializeLevel(upload.Level, width, height);

                            GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X, upload.Bounds.Y, upload.Bounds.Width, upload.Bounds.Height, upload.Format, PixelType.UnsignedByte,
                                             dataPointer);
                        }
                    }
                    // Just update content of the current texture
                    else if (dataPointer != IntPtr.Zero)
                    {
                        GLWrapper.BindTexture(this);

                        if (!manualMipmaps && upload.Level > 0)
                        {
                            //allocate mipmap levels
                            int level = 1;
                            int d     = 2;

                            while (width / d > 0)
                            {
                                initializeLevel(level, width / d, height / d);
                                level++;
                                d *= 2;
                            }

                            manualMipmaps = true;
                        }

                        int div = (int)Math.Pow(2, upload.Level);

                        GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X / div, upload.Bounds.Y / div, upload.Bounds.Width / div, upload.Bounds.Height / div, upload.Format,
                                         PixelType.UnsignedByte, dataPointer);
                    }
                }
                finally
                {
                    h0?.Free();
                    upload.Dispose();
                }
            }

            if (didUpload && !manualMipmaps)
            {
                GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest);
                GL.GenerateMipmap(TextureTarget.Texture2D);
            }

            return(didUpload);
        }
        public ILearner GetLearner(int result)
        {
            ILearner learner = null;

            switch (result)
            {
            case 1:
                learner = new ThreadSafety();
                break;

            case 2:
                learner = new ThreadAffinityApp();
                break;

            case 3:
                learner = new SignalAutoEvent();
                break;

            case 4:
                learner = new TwoWaySignal();
                break;

            case 5:
                learner = new SignalManualReset();
                break;

            case 6:
                learner = new CountDown();
                break;

            case 7:
                learner = new TPLIntro();
                break;

            case 8:
                learner = new ParallelVsNormal();
                break;

            case 9:
                learner = new Cancellation();
                break;

            case 10:
                learner = new ContinuationWithState();
                break;

            case 11:
                learner = new TaskCompletionSource();
                break;

            case 12:
                learner = new PLINQIntro();
                break;

            case 13:
                learner = new PLINQDegreeParallelism();
                break;

            case 14:
                learner = new PLINQForAll();
                break;

            case 15:
                learner = new PLINQMergeOptions();
                break;

            case 16:
                learner = new TAPIntro();
                break;

            default:
                learner = new ThreadSafety();
                break;
            }
            return(learner);
        }