private void Allocate(int sizeX, out int textureIdx, out int x, out int y) { // Look for space in existing textures. for (int i = 0; i < cacheTextures.Count; i++) { if (TryAllocateFromTexture(cacheTextures[i], sizeX, out x, out y)) { textureIdx = i; return; } } // Create new texture. var texture = new CacheTexture(); texture.bmp = graphics.CreateEmptyBitmap(PatternCacheTextureSize, PatternCacheTextureSize); InitCacheRows(texture); textureIdx = cacheTextures.Count; cacheTextures.Add(texture); // Allocation cannot fail here. var allocated = TryAllocateFromTexture(texture, sizeX, out x, out y); Debug.Assert(allocated); }
private bool TryAllocateFromTexture(CacheTexture texture, int sizeX, out int x, out int y) { Debug.Assert(texture.rows.Length == PatternCacheTextureSize / clampedPatternCacheSizeY); for (int j = 0; j < texture.rows.Length; j++) { var row = texture.rows[j]; if (row.freeEntries.Count > 0) { for (int k = 0; k < row.freeEntries.Count; k++) { var free = row.freeEntries[k]; if (free.sizeX >= sizeX) { CacheEntry node; if (free.sizeX > sizeX) { // Create new node. node = new CacheEntry(); node.startX = free.startX; node.sizeX = sizeX; // Shrink free node. free.startX += sizeX; free.sizeX -= sizeX; } else // Perfect fit, use as is. { node = free; row.freeEntries.RemoveAt(k); } x = node.startX; y = j * clampedPatternCacheSizeY; InsertAndMerge(row.usedEntries, node); return(true); } } } } x = -1; y = -1; return(false); }
private void InitCacheRows(CacheTexture texture) { var numRows = PatternCacheTextureSize / clampedPatternCacheSizeY; texture.rows = new CacheRow[numRows]; for (int i = 0; i < numRows; i++) { texture.rows[i] = new CacheRow(); texture.rows[i].freeEntries.Add(new CacheEntry() { startX = 0, sizeX = PatternCacheTextureSize }); } }
private void fillMotionBlurCache(SceneDescription sd, Texture[] motionblurCache, CacheTexture sum, double t0, double dt) { double t = t0-dt; Texture tex; for(int i = motionblurCache.Length-0x02; i >= 0x00; i--) { tex = buildCameraCalculateAt(sd, t); motionblurCache[i] = tex; sum.AddTexture(tex); t -= dt; } }
public void Execute(SceneDescription description) { double min = Math.Max(this.T0, description.SceneGraph.T0); double max = this.T1; double dt = (max-min)/this.TimeSamples; uint nDelta = (uint)Math.Round(this.ClosureTime/dt)+0x01; Texture[] motionblurCache = new Texture[nDelta]; CacheTexture blurCache = new CacheTexture((int)description.CameraWrapper.Width, (int)description.CameraWrapper.Height); Texture tex; this.fillMotionBlurCache(description, motionblurCache, blurCache, min, dt); if(this.Task == SuperCameraTask.MakeImage) { blurCache.AddTexture(this.buildCameraCalculateAt(description, min)); blurCache.MixWithAlpha(nDelta).Save(this.outputFile); } else if(this.Task == SuperCameraTask.MakeMovie) { this.clearTmpFolder(); int index = 0; Process proc = new Process(); proc.StartInfo.FileName = "convert"; string imagename; string jpegname; uint j = nDelta-0x01; for(double t = min; t <= max; t += dt) { imagename = string.Format("/tmp/output{0}.png", index.ToString("00000")); jpegname = string.Format("{0} /tmp/output{1}.jpg", imagename, index.ToString("00000")); tex = this.buildCameraCalculateAt(description, t); blurCache.RemoveTexture(motionblurCache[j]); blurCache.AddTexture(tex); blurCache.MixWithAlpha(nDelta).Save(imagename); motionblurCache[j++] = tex; j %= nDelta; index++; proc.WaitForExit(); proc.StartInfo.Arguments = jpegname; proc.Start(); } proc.WaitForExit(); this.convertToMovie(); this.clearTmpFolder(); } }
private void PreDeviceReset_Atlas() { // when device is going to be reset, all render targets will lose their content; // so unload all glyphs here; they'll be reloaded if they are drawn again m_loadedGlyphs.Clear(); for (int i = 0; i < m_cacheTextures.Count; ++i) { var tex = new CacheTexture(); tex.m_physicalRTTexture = m_cacheTextures[i].m_physicalRTTexture; m_cacheTextures[i] = tex; } }
private int RequestPage() { for (int i = 0; i < m_cacheTextures.Count; ++i) { var ct = m_cacheTextures[i]; for (int j = 0; j < ct.m_pageOccupied.Length; ++j) { if (!ct.m_pageOccupied[j]) { ct.m_pageOccupied[j] = true; return i * PagesInOneCacheTexture + j; } } } // find the least used glyph KeyValuePair<uint, GlyphData> leastUsedGlyph = new KeyValuePair<uint,GlyphData>(0, null); foreach (var kvp in m_loadedGlyphs) { if (leastUsedGlyph.Value == null || kvp.Value.m_timeStamp < leastUsedGlyph.Value.m_timeStamp) { leastUsedGlyph = kvp; } } if (leastUsedGlyph.Value == null || leastUsedGlyph.Value.m_timeStamp >= m_timeStamp - MinimalPageLife) { var cacheTexture = new CacheTexture(); cacheTexture.m_physicalRTTexture = m_cacheTextures.Count % 4 == 0 ? new RenderTarget2D(GameApp.Instance.GraphicsDevice, CacheTextureSize, CacheTextureSize, true, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents) : m_cacheTextures.Last().m_physicalRTTexture; cacheTexture.m_pageOccupied[0] = true; m_cacheTextures.Add(cacheTexture); return (m_cacheTextures.Count - 1) * PagesInOneCacheTexture; } else { // release the glyph foreach (var pageIndex in leastUsedGlyph.Value.m_pageIndices) { var textureIndex = pageIndex / PagesInOneCacheTexture; var localIndex = pageIndex % PagesInOneCacheTexture; m_cacheTextures[textureIndex].m_pageOccupied[localIndex] = false; } var retIndex = leastUsedGlyph.Value.m_pageIndices[0, 0]; m_cacheTextures[retIndex / PagesInOneCacheTexture].m_pageOccupied[retIndex % PagesInOneCacheTexture] = true; m_loadedGlyphs.Remove(leastUsedGlyph.Key); return retIndex; } }