/// <summary>
        /// Blits the front buffer to a system buffer and returns a Bitmap from that buffer
        /// </summary>
        /// <param name="Rectangle">Region to capture</param>
        /// <returns>Returns a Bitmap with the front buffer contents</returns>
        public System.Drawing.Bitmap GetCropFrontBuffer(ref System.Drawing.Rectangle Rectangle)
        {
            // crop the rectangle if it's too large, correcting it
            if (Rectangle.Width > blit.Description.Width)
            {
                Rectangle.Width = blit.Description.Width;
            }
            if (Rectangle.Height > blit.Description.Height)
            {
                Rectangle.Height = blit.Description.Height;
            }
            try
            {
                // update the system surface
                display.GetRenderTargetData(front, blit);

                // do the normal stuff but this time from the systemSurface
                int Pitch;
                // lock it
                Microsoft.DirectX.GraphicsStream gs = blit.LockRectangle(Rectangle, LockFlags.None, out Pitch);
                // create bitmap (this might be the slow call for this process)
                Bitmap b = new Bitmap(Rectangle.Width, Rectangle.Height, Pitch, System.Drawing.Imaging.PixelFormat.Format32bppArgb, gs.InternalData);
                //Bitmap b=null;
                // unlock
                blit.UnlockRectangle();
                // return our bitmap
                return(b);
            }
            catch (Exception)
            {
                try
                {
                    blit.UnlockRectangle();
                }
                catch (Exception) {}
                return(null);
            }
        }
Пример #2
0
        ///<summary>
        ///    Lock a box
        ///</summary>
        public override PixelBox LockImpl(BasicBox lockBox, BufferLocking options)
        {
            // Check for misuse
            if (((int)usage & (int)TextureUsage.RenderTarget) != 0)
            {
                throw new Exception("DirectX does not allow locking of or directly writing to RenderTargets. Use BlitFromMemory if you need the contents; " +
                                    "in D3D9HardwarePixelBuffer.LockImpl");
            }
            // Set extents and format
            PixelBox rval = new PixelBox(lockBox, format);

            // Set locking flags according to options
            D3D.LockFlags flags = D3D.LockFlags.None;
            switch (options)
            {
            case BufferLocking.Discard:
                // D3D only likes D3D.LockFlags.Discard if you created the texture with D3DUSAGE_DYNAMIC
                // debug runtime flags this up, could cause problems on some drivers
                if ((usage & BufferUsage.Dynamic) != 0)
                {
                    flags |= D3D.LockFlags.Discard;
                }
                break;

            case BufferLocking.ReadOnly:
                flags |= D3D.LockFlags.ReadOnly;
                break;

            default:
                break;
            }

            if (surface != null)
            {
                // Surface
                GraphicsStream data = null;
                int            pitch;
                if (lockBox.Left == 0 && lockBox.Top == 0 &&
                    lockBox.Right == width && lockBox.Bottom == height)
                {
                    // Lock whole surface
                    data = surface.LockRectangle(flags, out pitch);
                }
                else
                {
                    Rectangle prect = ToD3DRectangle(lockBox);             // specify range to lock
                    data = surface.LockRectangle(prect, flags, out pitch);
                }
                if (data == null)
                {
                    throw new Exception("Surface locking failed; in D3D9HardwarePixelBuffer.LockImpl");
                }
                FromD3DLock(rval, pitch, data);
            }
            else
            {
                // Volume
                D3D.Box       pbox = ToD3DBox(lockBox); // specify range to lock
                D3D.LockedBox lbox;                     // Filled in by D3D

                GraphicsStream data = volume.LockBox(pbox, flags, out lbox);
                FromD3DLock(rval, lbox, data);
            }
            return(rval);
        }
Пример #3
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();
            }
        }
        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;
            }
        }