public override Microsoft.DirectX.Direct3D.Surface Lock(int surface) { if (!textureLock) { D3d.Surface lockedSurface = d3dTexture.GetSurfaceLevel(0); textureLock = true; return(lockedSurface); } return(null); }
public Texture TakeScreenshot() { DisplayMode dm = device.DisplayMode; Microsoft.DirectX.Direct3D.Texture shot = new Microsoft.DirectX.Direct3D.Texture(device, dm.Width, dm.Height, 1, 0, Format.A8R8G8B8, Pool.SystemMemory); device.GetFrontBufferData(0, shot.GetSurfaceLevel(0)); System.Drawing.Rectangle rect; if (fullscreen) { rect = new Rectangle(0, 0, width, height); } else { rect = new Rectangle(Kernel.Form.PointToScreen(new System.Drawing.Point(0, 0)), new Size(width, height)); } int[] pixels = (int[])shot.LockRectangle(typeof(int), 0, LockFlags.None, dm.Width * dm.Height); Texture res = new Texture(width, height); int i = 0; for (int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { res[i++] = Color.FromColorCode(pixels[x + y * dm.Width]); } } shot.UnlockRectangle(0); return(res); }
/// <summary> /// Creates the texture as a render target. /// </summary> public Texture(Renderer renderer, int width, int height, bool alpha) { if (renderer == null) throw new ArgumentNullException("renderer", "Unable to create texture without a valid renderer reference."); this.renderer = renderer; try { d3dTexture = new Microsoft.DirectX.Direct3D.Texture(renderer.Device, width, height, 1, Usage.RenderTarget, alpha ? Format.A8R8G8B8 : Format.X8R8G8B8, Pool.Default); d3dSurface = d3dTexture.GetSurfaceLevel(0); this.size = new Size(width, height); this.hasAlpha = alpha; loaded = true; renderer.AddGraphicsObject(this); } catch (Exception ex) { loaded = false; Log.Write("Failed to create texture as render target, will use empty texture!" + " Error: " + ex.ToString()); } }
///<summary> /// @copydoc HardwarePixelBuffer.BlitToMemory ///</summary> public override void BlitToMemory(BasicBox srcBox, PixelBox dst) { // Decide on pixel format of temp surface PixelFormat tmpFormat = format; if (D3DHelper.ConvertEnum(dst.Format) == D3D.Format.Unknown) { tmpFormat = dst.Format; } if (surface != null) { Debug.Assert(srcBox.Depth == 1 && dst.Depth == 1); // Create temp texture D3D.Texture tmp = new D3D.Texture(device, dst.Width, dst.Height, 1, // 1 mip level ie topmost, generate no mipmaps 0, D3DHelper.ConvertEnum(tmpFormat), Pool.Scratch); D3D.Surface subSurface = tmp.GetSurfaceLevel(0); // Copy texture to this temp surface Rectangle destRect, srcRect; srcRect = ToD3DRectangle(srcBox); destRect = ToD3DRectangleExtent(dst); SurfaceLoader.FromSurface(subSurface, destRect, surface, srcRect, Filter.None, 0); // Lock temp surface and copy it to memory int pitch; // Filled in by D3D GraphicsStream data = subSurface.LockRectangle(D3D.LockFlags.ReadOnly, out pitch); // Copy it PixelBox locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat); FromD3DLock(locked, pitch, data); PixelUtil.BulkPixelConversion(locked, dst); subSurface.UnlockRectangle(); // Release temporary surface and texture subSurface.Dispose(); tmp.Dispose(); } else { // Create temp texture D3D.VolumeTexture tmp = new D3D.VolumeTexture(device, dst.Width, dst.Height, dst.Depth, 0, D3D.Usage.None, D3DHelper.ConvertEnum(tmpFormat), Pool.Scratch); D3D.Volume subVolume = tmp.GetVolumeLevel(0); // Volume D3D.Box ddestBox = ToD3DBoxExtent(dst); D3D.Box dsrcBox = ToD3DBox(srcBox); VolumeLoader.FromVolume(subVolume, ddestBox, volume, dsrcBox, Filter.None, 0); // Lock temp surface and copy it to memory D3D.LockedBox lbox; // Filled in by D3D GraphicsStream data = subVolume.LockBox(LockFlags.ReadOnly, out lbox); // Copy it PixelBox locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat); FromD3DLock(locked, lbox, data); PixelUtil.BulkPixelConversion(locked, dst); subVolume.UnlockBox(); // Release temporary surface and texture subVolume.Dispose(); tmp.Dispose(); } }
public void RefreshTexture() { if (tileData != null && dirtyImage) { EnsureTextureIsDynamic(); // Unload texture & recreate if needed Texture texture = TextureManager.Instance.GetByName(textureName); if (texture == null) { // We couldn't find the texture. It might be that we're in // the midst of swapping them at the DirectX level (this is // only speculation) return; } if (texture is D3DTexture) { // Turns out that to get performance, not only did I have to go // straight to DirectX, unsafe code is much faster as well. What // we're doing here is keeping a temporary surface around that we // can lock and draw to at our leisure, then copying the surface // over to the correct texture data when we're done. To do this, // the easiest way is to lock the desired rectangle on the temp // surface, and get a graphics stream object back from it. You // might think you could then use byte arrays, or even ask for // an Array of bytes back from LockRectangle, but not only was // that slower, it also produced unpredictable results, possibly // due to storing the array in row order vs. column order in the // native vs. managed areas. // // The temporary surface is necessary because, well, I could // never seem to acquire the lock on the real surface. However, // an offscreen plain surface (as used above) seems to lock fine. // // Next caveat: The pointer on the graphics stream points to the // start of the row of the locked rectangle. You'd be surprised // how long it took me to figure that one out. Further, it's // important to use the pitch returned by LockRectangle to adjust // your row array position, as the pitch may or may not be your // surface width in bytes. (Some drivers store extra data on the // ends of the rows, it seems.) Rectangle lockRect = new Rectangle(); lockRect.X = dirtyArea.X; lockRect.Y = dirtyArea.Y; lockRect.Width = dirtyArea.Width; lockRect.Height = dirtyArea.Height; D3D.Texture t = (texture as D3DTexture).DXTexture as D3D.Texture; int pitch; int bpp = PixelUtil.GetNumElemBytes(texture.Format); D3D.Surface dst = t.GetSurfaceLevel(0); DX.GraphicsStream g = dynamicSurface.LockRectangle(lockRect, D3D.LockFlags.NoSystemLock, out pitch); unsafe { uint *dstArray = (uint *)g.InternalDataPointer; pitch /= sizeof(uint); for (int z = 0; z < lockRect.Height; z++) { for (int x = 0; x < lockRect.Width; x++) { uint data = GetData(x + lockRect.X, z + lockRect.Y); uint converted = ConvertPixel(data, INTERNAL_DATA_FORMAT, texture.Format); dstArray[z * pitch + x] = converted; } } } dynamicSurface.UnlockRectangle(); D3D.SurfaceLoader.FromSurface(dst, dynamicSurface, D3D.Filter.None, 0); } else { #if false // following code is for blitting only the dirty rectangle BasicBox destBox = new BasicBox(dirtyArea.X, dirtyArea.Y, dirtyArea.X + dirtyArea.Width, dirtyArea.Y + dirtyArea.Height); PixelBox srcPixel = textureImage.GetPixelBox(0, 0); BasicBox srcBox = new BasicBox(0, 0, dirtyArea.Width, dirtyArea.Height); PixelBox trimmedSrcPixel = srcPixel.GetSubVolume(srcBox); buffer.BlitFromMemory(trimmedSrcPixel, destBox); #endif } // Clean up dirty bit dirtyImage = false; dirtyArea.X = 0; dirtyArea.Y = 0; dirtyArea.Width = 0; dirtyArea.Height = 0; } }
///<summary> /// @copydoc HardwarePixelBuffer.BlitToMemory ///</summary> public override void BlitToMemory(BasicBox srcBox, PixelBox dst) { // Decide on pixel format of temp surface PixelFormat tmpFormat = format; if (D3DHelper.ConvertEnum(dst.Format) == D3D.Format.Unknown) tmpFormat = dst.Format; if (surface != null) { Debug.Assert(srcBox.Depth == 1 && dst.Depth == 1); // Create temp texture D3D.Texture tmp = new D3D.Texture(device, dst.Width, dst.Height, 1, // 1 mip level ie topmost, generate no mipmaps 0, D3DHelper.ConvertEnum(tmpFormat), Pool.Scratch); D3D.Surface subSurface = tmp.GetSurfaceLevel(0); // Copy texture to this temp surface Rectangle destRect, srcRect; srcRect = ToD3DRectangle(srcBox); destRect = ToD3DRectangleExtent(dst); SurfaceLoader.FromSurface(subSurface, destRect, surface, srcRect, Filter.None, 0); // Lock temp surface and copy it to memory int pitch; // Filled in by D3D GraphicsStream data = subSurface.LockRectangle(D3D.LockFlags.ReadOnly, out pitch); // Copy it PixelBox locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat); FromD3DLock(locked, pitch, data); PixelUtil.BulkPixelConversion(locked, dst); subSurface.UnlockRectangle(); // Release temporary surface and texture subSurface.Dispose(); tmp.Dispose(); } else { // Create temp texture D3D.VolumeTexture tmp = new D3D.VolumeTexture(device, dst.Width, dst.Height, dst.Depth, 0, D3D.Usage.None, D3DHelper.ConvertEnum(tmpFormat), Pool.Scratch); D3D.Volume subVolume = tmp.GetVolumeLevel(0); // Volume D3D.Box ddestBox = ToD3DBoxExtent(dst); D3D.Box dsrcBox = ToD3DBox(srcBox); VolumeLoader.FromVolume(subVolume, ddestBox, volume, dsrcBox, Filter.None, 0); // Lock temp surface and copy it to memory D3D.LockedBox lbox; // Filled in by D3D GraphicsStream data = subVolume.LockBox(LockFlags.ReadOnly, out lbox); // Copy it PixelBox locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat); FromD3DLock(locked, lbox, data); PixelUtil.BulkPixelConversion(locked, dst); subVolume.UnlockBox(); // Release temporary surface and texture subVolume.Dispose(); tmp.Dispose(); } }