public override TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset)
        {
            PixelBox sourceBox;
            int      mipCount = image.NumMipmaps;

            if (mipCount == 0) //We always have to take from the largest size
            {
                sourceBox = image.getPixelBox(0, 0);
            }
            else
            {
                sourceBox = image.getPixelBox(0, (uint)(page.mip - mipOffset));
            }

            IntSize2 largestSupportedPageIndex = indirectionTexture.NumPages;

            largestSupportedPageIndex.Width  >>= page.mip;
            largestSupportedPageIndex.Height >>= page.mip;
            if (page.x != 0 && page.y != 0 && page.x + 1 != largestSupportedPageIndex.Width && page.y + 1 != largestSupportedPageIndex.Height)
            {
                //Can grab a complete page from the texture
                sourceBox.Rect = new IntRect(page.x * textelsPerPage - padding, page.y * textelsPerPage - padding, textelsPerPage + padding2, textelsPerPage + padding2);
            }
            else
            {
                //Have to get a partial page
                sourceBox.Rect = new IntRect(page.x * textelsPerPage, page.y * textelsPerPage, textelsPerPage, textelsPerPage);
            }

            return(new TexturePageHandle(sourceBox, this));
        }
        private void fillOutLowerMips(VTexPage vTextPage, IntColor color, Func <IntColor, IntColor, bool> writePixel)
        {
            //Fill in lower (more textels) mip levels
            uint     x         = vTextPage.x;
            uint     y         = vTextPage.y;
            uint     w         = 1;
            uint     h         = 1;
            IntColor readPixel = new IntColor();

            for (int i = vTextPage.mip - 1; i >= 0; --i)
            {
                //This is probably really slow
                x = x << 1;
                y = y << 1;
                w = w << 1;
                h = h << 1;
                var mipLevelBitmap = fiBitmap[i];
                for (uint xi = 0; xi < w; ++xi)
                {
                    for (uint yi = 0; yi < h; ++yi)
                    {
                        readPixel.ARGB = mipLevelBitmap.getColorAtARGB(x + xi, y + yi, 0);
                        if (writePixel.Invoke(color, readPixel))
                        {
                            mipLevelBitmap.setColorAtARGB(color.ARGB, x + xi, y + yi, 0);
                        }
                    }
                }
            }
        }
        public override TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset)
        {
            int  mip           = page.mip;
            int  x             = page.x;
            int  y             = page.y;
            bool halfSizePages = textelsPerPage != pagedImage.PageSize;

            if (halfSizePages)
            {
                x /= 2;
                y /= 2;
            }

            var image    = pagedImage.getImage(x, y, mip - mipOffset);
            var pixelBox = image.getPixelBox();

            if (halfSizePages && image.Width == pagedImage.PageSize + padding2)
            {
                int subpageX       = page.x % 2;
                int subpageY       = page.y % 2;
                int offsetMultiple = (int)image.Width / 2 - padding;
                int halfSize       = textelsPerPage + padding2;

                pixelBox.Rect = new Engine.IntRect(offsetMultiple * subpageX, offsetMultiple * subpageY, halfSize, halfSize);
            }

            return(new TexturePageHandle(pixelBox, this, image));
        }
Exemple #4
0
        private bool copyToStaging(VTexPage page, StagingBufferSet buffers, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit)
        {
            bool usedPhysicalPage = false;

            try
            {
                if (page.mip >= textureUnit.MipOffset)
                {
                    //Load or grab from cache
                    using (var pageHandle = textureCache.getImage(page, indirectionTexture, textureUnit, textelsPerPage, padding, padding2))
                    {
                        buffers.setPhysicalPage(pageHandle.PixelBox, virtualTextureManager.getPhysicalTexture(textureUnit.TextureUnit), padding);
                        usedPhysicalPage = true;
                    }
                }
                else
                {
                    Logging.Log.Warning("Unable to load mip map level {0} for texture {1}", page.mip - textureUnit.MipOffset, textureUnit.TextureFileName);
                }
            }
            catch (Exception ex)
            {
                Logging.Log.Error("{0} loading image {1}. Message: {2}", ex.GetType().Name, textureUnit.TextureFileName, ex.Message);
            }
            return(usedPhysicalPage);
        }
        internal void processPage(float u, float v, byte mip)
        {
            ++numRequests;
            VTexPage page;

            if (mip >= highestMip)
            {
                page = new VTexPage(0, 0, (byte)(highestMip - 1), id);
            }
            else
            {
                IntSize2 mipLevelNumPages = numPages / (1 << mip);
                byte     x = (byte)(u * mipLevelNumPages.Width);
                byte     y = (byte)(v * mipLevelNumPages.Height);
                if (x == mipLevelNumPages.Width)
                {
                    --x;
                }
                if (y == mipLevelNumPages.Height)
                {
                    --y;
                }
                page = new VTexPage(x, y, mip, id);
            }
            if (activePages.Contains(page))
            {
                visibleThisUpdate.Add(page);
            }
            else
            {
                addedPages.Add(page);
            }
        }
Exemple #6
0
        public override bool Equals(object obj)
        {
            VTexPage other = obj as VTexPage;

            if (other != null)
            {
                return(this.hashCode == other.hashCode);
            }
            return(false);
        }
Exemple #7
0
        private bool loadPage(VTexPage page, StagingBufferSet stagingBuffers)
        {
            bool added = false;

            try
            {
                //First see if we still have that page in our virtual texture pool, possible optimization to sort these to the front of the list
                if (physicalPageQueue.Count > 0)              //Do we have pages available
                {
                    PTexPage pTexPage = physicalPageQueue[0]; //The physical page candidate, do not modify before usedPhysicalPages if statement below
                    if (loadImages(page, pTexPage, stagingBuffers))
                    {
                        //Alert old texture of removal if there was one, Do not modify pTexPage above this if block, we need the old data
                        IndirectionTexture oldIndirectionTexture = null;
                        if (pTexPage.VirtualTexturePage != null)
                        {
                            if (virtualTextureManager.getIndirectionTexture(pTexPage.VirtualTexturePage.indirectionTexId, out oldIndirectionTexture))
                            {
                                oldIndirectionTexture.removePhysicalPage(pTexPage);
                            }

                            physicalPagePool.Remove(pTexPage.VirtualTexturePage); //Be sure to remove the page from the pool if it was used previously
                        }

                        physicalPageQueue.RemoveAt(0);
                        pTexPage.VirtualTexturePage = page;
                        usedPhysicalPages.Add(page, pTexPage);

                        //Add to new indirection texture
                        IndirectionTexture newIndirectionTex;
                        if (virtualTextureManager.getIndirectionTexture(page.indirectionTexId, out newIndirectionTex))
                        {
                            newIndirectionTex.addPhysicalPage(pTexPage);
                            stagingBuffers.setIndirectionTextures(oldIndirectionTexture, newIndirectionTex);
                        }
                        added = true;
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.Log.Debug("{0} loading page {1}. Message: {2}", ex.GetType().Name, page.ToString(), ex.Message);
            }
            return(added);
        }
Exemple #8
0
        /// <summary>
        /// Load the given image. Note that pTexPage is constant for the duration of this function call
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pTexPage"></param>
        /// <returns></returns>
        private bool loadImages(VTexPage page, PTexPage pTexPage, StagingBufferSet stagingBuffers)
        {
            int  stagingImageIndex = 0;
            bool usedPhysicalPage  = false;
            IndirectionTexture indirectionTexture;

            if (virtualTextureManager.getIndirectionTexture(page.indirectionTexId, out indirectionTexture))
            {
                //Fire off image loading and blitting tasks
                foreach (var textureUnit in indirectionTexture.OriginalTextures)
                {
                    copyTostagingImageTasks[stagingImageIndex] = fireCopyToStaging(page, stagingBuffers, indirectionTexture, textureUnit);
                    ++stagingImageIndex;
                }
                //Wait for results
                for (int i = 0; i < stagingImageIndex; ++i)
                {
                    copyTostagingImageTasks[i].Wait();
                    if (copyTostagingImageTasks[i].Result)
                    {
                        usedPhysicalPage = true;
                    }
                }

                //Single threaded
                //foreach (var textureUnit in indirectionTexture.OriginalTextures)
                //{
                //    if (copyToStaging(page, stagingBuffers, indirectionTexture, textureUnit))
                //    {
                //        usedPhysicalPage = true;
                //    }
                //}

                //Update staging buffer info
                stagingBuffers.Dest = new IntRect(pTexPage.x, pTexPage.y, textelsPerPhysicalPage, textelsPerPhysicalPage);
            }
            return(usedPhysicalPage);
        }
        internal TexturePageHandle getImage(VTexPage page, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit, int textelsPerPage, int padding, int padding2)
        {
            String textureName;

            if (texturesArePaged)
            {
                textureName = textureUnit.TextureFileName;
            }
            else
            {
                textureName = String.Format("{0}_{1}", textureUnit.TextureFileName, indirectionTexture.RealTextureSize.Width >> page.mip);
            }
            TextureCacheHandle cacheHandle;

            if (!this.TryGetValue(textureName, out cacheHandle))
            {
                String file = textureUnit.TextureFileName;
                if (texturesArePaged) //Paged Images
                {
                    //using (var perfMon = new LogPerformanceBlock(String.Format("Loaded image {0} in {{0}} ms", file), Logging.LogLevel.Info, "TextureCache"))
                    //{
                    PagedImage pagedImage = new PagedImage();
                    pagedImage.load(() => VirtualFileSystem.Instance.openStream(file, Engine.Resources.FileMode.Open, Engine.Resources.FileAccess.Read));
                    cacheHandle = this.Add(textureName, pagedImage);
                    //}
                }
                else //Normal Images
                {
                    String extension  = Path.GetExtension(file);
                    String directFile = textureUnit.TextureFileName.Substring(0, file.Length - extension.Length);
                    directFile = String.Format("{0}_{1}{2}", directFile, indirectionTexture.RealTextureSize.Width >> page.mip, extension);
                    if (VirtualFileSystem.Instance.exists(directFile))
                    {
                        var image = doLoadImage(extension, directFile);
                        cacheHandle = this.Add(textureName, image);
                    }
                    else
                    {
                        //Not using cache for full size images, this is a rare case that we are not really supporting right now
                        Image image = doLoadImage(extension, textureUnit.TextureFileName);

                        //If we aren't mip 0 resize accordingly
                        if (page.mip > image.NumMipmaps && page.mip != 0)
                        {
                            using (Image original = image)
                            {
                                image = new Image(original.Width >> page.mip, original.Height >> page.mip, original.Depth, original.Format, original.NumFaces, original.NumMipmaps);
                                using (var src = original.getPixelBox())
                                {
                                    using (var dest = image.getPixelBox())
                                    {
                                        Image.Scale(src, dest, Image.Filter.FILTER_BILINEAR);
                                    }
                                }
                            }
                        }
                        cacheHandle = this.Add(textureName, image);
                    }
                }
            }
            return(cacheHandle.createTexturePageHandle(page, indirectionTexture, padding, padding2, textelsPerPage, textureUnit.MipOffset));
        }
Exemple #10
0
 private Task <bool> fireCopyToStaging(VTexPage page, StagingBufferSet buffers, IndirectionTexture indirectionTexture, OriginalTextureInfo textureUnit)
 {
     return(Task.Run(() => copyToStaging(page, buffers, indirectionTexture, textureUnit)));
 }
Exemple #11
0
 public void removeRequestedPage(VTexPage page)
 {
     addedPages.Remove(page);
     removedPages.Add(page);
 }
Exemple #12
0
 public void addRequestedPage(VTexPage page)
 {
     addedPages.Add(page);
 }
Exemple #13
0
 /// <summary>
 /// Create a texture page handle for this cache handle, the page will be selected from the given info.
 /// You must dispose the handle that is returned.
 /// </summary>
 /// <param name="page"></param>
 /// <param name="indirectionTexture"></param>
 /// <param name="padding"></param>
 /// <param name="padding2"></param>
 /// <param name="textelsPerPage"></param>
 /// <returns></returns>
 public abstract TexturePageHandle createTexturePageHandle(VTexPage page, IndirectionTexture indirectionTexture, int padding, int padding2, int textelsPerPage, int mipOffset);