예제 #1
0
        protected override PixelBox LockImpl(BasicBox lockBox, BufferLocking options)
        {
            //Entering critical section
            LockDeviceAccess();

            // Check for misuse
            if (((int)usage & (int)TextureUsage.RenderTarget) != 0)
            {
                throw new AxiomException(
                          "DirectX does not allow locking of or directly writing to RenderTargets. Use BlitFromMemory if you need the contents.");
            }

            // Set locking flags according to options
            var flags = D3D9Helper.ConvertEnum(options, usage);

            if (this.mapDeviceToBufferResources.Count == 0)
            {
                throw new AxiomException("There are no resources attached to this pixel buffer !!");
            }

            lockedBox      = lockBox;
            this.lockFlags = flags;

            var bufferResources = this.mapDeviceToBufferResources.First().Value;

            // Lock the source buffer.
            var lockedBuf = LockBuffer(bufferResources, lockBox, flags);

            //Leaving critical section
            UnlockDeviceAccess();

            return(lockedBuf);
        }
예제 #2
0
        public void Bind(D3D9.Device dev, D3D9.Volume volume, D3D9.BaseTexture mipTex)
        {
            //Entering critical section
            LockDeviceAccess();

            var bufferResources = GetBufferResources(dev);
            var isNewBuffer     = false;

            if (bufferResources == null)
            {
                bufferResources = new BufferResources();
                this.mapDeviceToBufferResources.Add(dev, bufferResources);
                isNewBuffer = true;
            }

            bufferResources.MipTex = mipTex;
            bufferResources.Volume = volume;

            var desc = volume.Description;

            width  = desc.Width;
            height = desc.Height;
            depth  = desc.Depth;
            format = D3D9Helper.ConvertEnum(desc.Format);
            // Default
            rowPitch    = Width;
            slicePitch  = Height * Width;
            sizeInBytes = PixelUtil.GetMemorySize(Width, Height, Depth, Format);

            if (isNewBuffer && this.ownerTexture.IsManuallyLoaded)
            {
                foreach (var it in this.mapDeviceToBufferResources)
                {
                    if (it.Value != bufferResources && it.Value.Volume != null && it.Key.TestCooperativeLevel().Success&&
                        dev.TestCooperativeLevel().Success)
                    {
                        var fullBufferBox = new BasicBox(0, 0, 0, Width, Height, Depth);
                        var dstBox        = new PixelBox(fullBufferBox, Format);

                        var data = new byte[sizeInBytes];
                        using (var d = BufferBase.Wrap(data))
                        {
                            dstBox.Data = d;
                            BlitToMemory(fullBufferBox, dstBox, it.Value, it.Key);
                            BlitFromMemory(dstBox, fullBufferBox, bufferResources);
                            Array.Clear(data, 0, sizeInBytes);
                        }
                        break;
                    }
                }
            }

            //Leaving critical section
            UnlockDeviceAccess();
        }
예제 #3
0
        public override Axiom.Media.PixelFormat GetNativeFormat(TextureType ttype, PixelFormat format, TextureUsage usage)
        {
            // Basic filtering
            var d3dPF = D3D9Helper.ConvertEnum(D3D9Helper.GetClosestSupported(format));

            // Calculate usage
            var d3dusage = D3D9.Usage.None;
            var pool     = D3D9.Pool.Managed;

            if ((usage & TextureUsage.RenderTarget) != 0)
            {
                d3dusage |= D3D9.Usage.RenderTarget;
                pool      = D3D9.Pool.Default;
            }
            if ((usage & TextureUsage.Dynamic) != 0)
            {
                d3dusage |= D3D9.Usage.Dynamic;
                pool      = D3D9.Pool.Default;
            }

            var curDevice = D3D9RenderSystem.ActiveD3D9Device;

            // Use D3DX to adjust pixel format
            switch (ttype)
            {
            case TextureType.OneD:
            case TextureType.TwoD:
                var tReqs = D3D9.Texture.CheckRequirements(curDevice, 0, 0, 0, d3dusage, D3D9Helper.ConvertEnum(format), pool);
                d3dPF = tReqs.Format;
                break;

            case TextureType.ThreeD:
                var volReqs = D3D9.VolumeTexture.CheckRequirements(curDevice, 0, 0, 0, 0, d3dusage,
                                                                   D3D9Helper.ConvertEnum(format), pool);
                d3dPF = volReqs.Format;
                break;

            case TextureType.CubeMap:
                var cubeReqs = D3D9.CubeTexture.CheckRequirements(curDevice, 0, 0, d3dusage, D3D9Helper.ConvertEnum(format),
                                                                  pool);
                d3dPF = cubeReqs.Format;
                break;
            }

            return(D3D9Helper.ConvertEnum(d3dPF));
        }
예제 #4
0
        /// <summary>
        /// Updates buffer resources from system memory buffer.
        /// </summary>
        private bool _updateBufferResources(BufferBase systemMemoryBuffer, ref BufferResources bufferResources)
        {
            Contract.RequiresNotNull(bufferResources, "Cannot update BufferResources in D3D9HardwareIndexBuffer!");
            Contract.RequiresNotNull(bufferResources.IndexBuffer, "Cannot update BufferResources in D3D9HardwareIndexBuffer!");
            Contract.Requires(bufferResources.IsOutOfDate);

            DX.DataStream dstBytes;

            // Lock the buffer
            try
            {
                dstBytes = bufferResources.IndexBuffer.Lock(bufferResources.LockOffset, bufferResources.LockLength,
                                                            D3D9Helper.ConvertEnum(bufferResources.LockOptions, usage));
            }
            catch (Exception ex)
            {
                throw new AxiomException("Cannot lock D3D9 index buffer!", ex);
            }

            using (var src = systemMemoryBuffer + bufferResources.LockOffset)
            {
                using (var dest = BufferBase.Wrap(dstBytes.DataPointer, (int)dstBytes.Length))
                {
                    Memory.Copy(src, dest, bufferResources.LockLength);
                }
            }

            // Unlock the buffer.
            var hr = bufferResources.IndexBuffer.Unlock();

            if (hr.Failure)
            {
                throw new AxiomException("Cannot unlock D3D9 index buffer: {0}", hr.ToString());
            }

            bufferResources.IsOutOfDate = false;
            bufferResources.LockOffset  = sizeInBytes;
            bufferResources.LockLength  = 0;
            bufferResources.LockOptions = BufferLocking.Normal;

            return(true);
        }
예제 #5
0
        public void CreateBuffer(D3D9.Device d3d9Device, D3D9.Pool ePool)
        {
            //Entering critical section
            this.LockDeviceAccess();

            BufferResources bufferResources;

            // Find the vertex buffer of this device.
            if (this._mapDeviceToBufferResources.TryGetValue(d3d9Device, out bufferResources))
            {
                bufferResources.IndexBuffer.SafeDispose();
            }
            else
            {
                bufferResources = new BufferResources();
                this._mapDeviceToBufferResources.Add(d3d9Device, bufferResources);
            }

            bufferResources.IndexBuffer   = null;
            bufferResources.IsOutOfDate   = true;
            bufferResources.LockOffset    = 0;
            bufferResources.LockLength    = sizeInBytes;
            bufferResources.LockOptions   = BufferLocking.Normal;
            bufferResources.LastUsedFrame = Root.Instance.NextFrameNumber;

            // Create the Index buffer
            try
            {
                bufferResources.IndexBuffer = new D3D9.IndexBuffer(d3d9Device, sizeInBytes, D3D9Helper.ConvertEnum(usage), ePool,
                                                                   D3D9Helper.ConvertEnum(type));
            }
            catch (Exception ex)
            {
                throw new AxiomException("Cannot create D3D9 Index buffer", ex);
            }

            this._bufferDesc = bufferResources.IndexBuffer.Description;

            //Leaving critical section
            this.UnlockDeviceAccess();
        }
        private bool _checkVertexTextureFormats(D3D9RenderWindow renderWindow)
        {
            var anySupported = false;

            var bbSurf     = (D3D9.Surface[])renderWindow["DDBACKBUFFER"];
            var bbSurfDesc = bbSurf[0].Description;

            for (var pf = PixelFormat.L8; pf < PixelFormat.Count; ++pf)
            {
                var fmt = D3D9Helper.ConvertEnum(D3D9Helper.GetClosestSupported(pf));
                if (
                    !this._pD3D.CheckDeviceFormat(this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format,
                                                  D3D9.Usage.QueryVertexTexture, D3D9.ResourceType.Texture, fmt))
                {
                    continue;
                }

                // cool, at least one supported
                anySupported = true;
                LogManager.Instance.Write("D3D9: Vertex texture format supported - {0}", PixelUtil.GetFormatName(pf));
            }

            return(anySupported);
        }
예제 #7
0
        protected void BlitToMemory(BasicBox srcBox, PixelBox dst, BufferResources srcBufferResources, D3D9.Device d3d9Device)
        {
            // Decide on pixel format of temp surface
            PixelFormat tmpFormat = Format;

            if (D3D9Helper.ConvertEnum(dst.Format) != D3D9.Format.Unknown)
            {
                tmpFormat = dst.Format;
            }

            if (srcBufferResources.Surface != null)
            {
                Debug.Assert(srcBox.Depth == 1 && dst.Depth == 1);
                var srcDesc  = srcBufferResources.Surface.Description;
                var temppool = D3D9.Pool.Scratch;

                // if we're going to try to use GetRenderTargetData, need to use system mem pool
                var tryGetRenderTargetData = false;
                if (((srcDesc.Usage & D3D9.Usage.RenderTarget) != 0) && (srcBox.Width == dst.Width) &&
                    (srcBox.Height == dst.Height) && (srcBox.Width == Width) && (srcBox.Height == Height) &&
                    (Format == tmpFormat))
                {
                    tryGetRenderTargetData = true;
                    temppool = D3D9.Pool.SystemMemory;
                }

                // Create temp texture
                var tmp = new D3D9.Texture(d3d9Device, dst.Width, dst.Height, 1,                  // 1 mip level ie topmost, generate no mipmaps
                                           0, D3D9Helper.ConvertEnum(tmpFormat), temppool);

                var surface = tmp.GetSurfaceLevel(0);

                // Copy texture to this temp surface
                var srcRect  = ToD3DRectangle(srcBox);
                var destRect = ToD3DRectangle(dst);

                // Get the real temp surface format
                var dstDesc = surface.Description;
                tmpFormat = D3D9Helper.ConvertEnum(dstDesc.Format);

                // Use fast GetRenderTargetData if we are in its usage conditions
                var fastLoadSuccess = false;
                if (tryGetRenderTargetData)
                {
                    var result = d3d9Device.GetRenderTargetData(srcBufferResources.Surface, surface);
                    fastLoadSuccess = result.Success;
                }
                if (!fastLoadSuccess)
                {
                    var res = D3D9.Surface.FromSurface(surface, srcBufferResources.Surface, D3D9.Filter.Default, 0, srcRect, destRect);
                    if (res.Failure)
                    {
                        surface.SafeDispose();
                        tmp.SafeDispose();
                        throw new AxiomException("D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.BlitToMemory");
                    }
                }

                // Lock temp surface and copy it to memory
                var lrect = surface.LockRectangle(D3D9.LockFlags.ReadOnly);

                // Copy it
                var locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat);
                FromD3DLock(locked, lrect);
                PixelConverter.BulkPixelConversion(locked, dst);
                surface.UnlockRectangle();
                // Release temporary surface and texture
                surface.SafeDispose();
                tmp.SafeDispose();
            }
            else if (srcBufferResources.Volume != null)
            {
                // Create temp texture
                var tmp = new D3D9.VolumeTexture(d3d9Device, dst.Width, dst.Height, dst.Depth, 0, 0,
                                                 D3D9Helper.ConvertEnum(tmpFormat), D3D9.Pool.Scratch);

                var surface = tmp.GetVolumeLevel(0);

                // Volume
                var ddestBox = ToD3DBoxExtent(dst);
                var dsrcBox  = ToD3DBox(srcBox);

                var res = D3D9.Volume.FromVolume(surface, srcBufferResources.Volume, D3D9.Filter.Default, 0, dsrcBox, ddestBox);
                if (res.Failure)
                {
                    surface.SafeDispose();
                    tmp.SafeDispose();
                    throw new AxiomException("D3D9.Surface.FromVolume failed in D3D9HardwarePixelBuffer.BlitToMemory");
                }

                // Lock temp surface and copy it to memory
                var lbox = surface.LockBox(D3D9.LockFlags.ReadOnly);                   // Filled in by D3D

                // Copy it
                var locked = new PixelBox(dst.Width, dst.Height, dst.Depth, tmpFormat);
                FromD3DLock(locked, lbox);
                PixelConverter.BulkPixelConversion(locked, dst);
                surface.UnlockBox();
                // Release temporary surface and texture
                surface.SafeDispose();
                tmp.SafeDispose();
            }
        }
예제 #8
0
        protected void BlitFromMemory(PixelBox src, BasicBox dstBox, BufferResources dstBufferResources)
        {
            // for scoped deletion of conversion buffer
            var converted = src;
            var bufSize   = 0;

            // convert to pixelbuffer's native format if necessary
            if (D3D9Helper.ConvertEnum(src.Format) == D3D9.Format.Unknown)
            {
                bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, Format);
                var newBuffer = new byte[bufSize];
                using (var data = BufferBase.Wrap(newBuffer))
                {
                    converted = new PixelBox(src.Width, src.Height, src.Depth, Format, data);
                }
                PixelConverter.BulkPixelConversion(src, converted);
            }

            int rowWidth = 0;

            if (PixelUtil.IsCompressed(converted.Format))
            {
                rowWidth = converted.RowPitch / 4;
                // D3D wants the width of one row of cells in bytes
                if (converted.Format == PixelFormat.DXT1)
                {
                    // 64 bits (8 bytes) per 4x4 block
                    rowWidth *= 8;
                }
                else
                {
                    // 128 bits (16 bytes) per 4x4 block
                    rowWidth *= 16;
                }
            }
            else
            {
                rowWidth = converted.RowPitch * PixelUtil.GetNumElemBytes(converted.Format);
            }

            if (dstBufferResources.Surface != null)
            {
                var srcRect  = ToD3DRectangle(converted);
                var destRect = ToD3DRectangle(dstBox);

                bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format);
                var data = new byte[bufSize];
                using (var dest = BufferBase.Wrap(data))
                {
                    Memory.Copy(converted.Data, dest, bufSize);
                }

                try
                {
                    D3D9.Surface.FromMemory(dstBufferResources.Surface, data, D3D9.Filter.Default, 0,
                                            D3D9Helper.ConvertEnum(converted.Format), rowWidth, srcRect, destRect);
                }
                catch (Exception e)
                {
                    throw new AxiomException("D3D9.Surface.FromMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e);
                }
            }
            else if (dstBufferResources.Volume != null)
            {
                var srcBox     = ToD3DBox(converted);
                var destBox    = ToD3DBox(dstBox);
                var sliceWidth = 0;
                if (PixelUtil.IsCompressed(converted.Format))
                {
                    sliceWidth = converted.SlicePitch / 16;
                    // D3D wants the width of one slice of cells in bytes
                    if (converted.Format == PixelFormat.DXT1)
                    {
                        // 64 bits (8 bytes) per 4x4 block
                        sliceWidth *= 8;
                    }
                    else
                    {
                        // 128 bits (16 bytes) per 4x4 block
                        sliceWidth *= 16;
                    }
                }
                else
                {
                    sliceWidth = converted.SlicePitch * PixelUtil.GetNumElemBytes(converted.Format);
                }

                bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format);
                var data = new byte[bufSize];
                using (var dest = BufferBase.Wrap(data))
                {
                    Memory.Copy(converted.Data, dest, bufSize);
                }

                //TODO note sliceWidth and rowWidth are ignored..
                D3D9.ImageInformation info;
                try
                {
                    //D3D9.D3DX9.LoadVolumeFromMemory() not accessible 'cause D3D9.D3DX9 static class is not public
                    D3D9.Volume.FromFileInMemory(dstBufferResources.Volume, data, D3D9.Filter.Default, 0, srcBox, destBox, null,
                                                 out info);
                }
                catch (Exception e)
                {
                    throw new AxiomException("D3D9.Volume.FromFileInMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e);
                }
            }

            if (this.doMipmapGen)
            {
                GenMipmaps(dstBufferResources.MipTex);
            }
        }
예제 #9
0
        public void CreateBuffer(D3D9.Device d3d9Device, D3D9.Pool ePool)
        {
            // Find the vertex buffer of this device.
            BufferResources bufferResources;

            if (this._mapDeviceToBufferResources.TryGetValue(d3d9Device, out bufferResources))
            {
                bufferResources.VertexBuffer.SafeDispose();
            }
            else
            {
                bufferResources = new BufferResources();
                this._mapDeviceToBufferResources.Add(d3d9Device, bufferResources);
            }

            bufferResources.VertexBuffer  = null;
            bufferResources.IsOutOfDate   = true;
            bufferResources.LockOffset    = 0;
            bufferResources.LockLength    = sizeInBytes;
            bufferResources.LockOptions   = BufferLocking.Normal;
            bufferResources.LastUsedFrame = Root.Instance.NextFrameNumber;

            // Create the vertex buffer
            try
            {
                bufferResources.VertexBuffer = new D3D9.VertexBuffer(d3d9Device, sizeInBytes, D3D9Helper.ConvertEnum(usage), 0,
                                                                     // No FVF here, thank you.
                                                                     ePool);
            }
            catch (Exception ex)
            {
                throw new AxiomException("Cannot restore D3D9 vertex buffer", ex);
            }

            this._bufferDesc = bufferResources.VertexBuffer.Description;
        }