Esempio n. 1
0
        /// <summary>
        /// </summary>
        /// <param name="srcBox"> </param>
        /// <param name="dst"> </param>
        public override void BlitToMemory(BasicBox srcBox, PixelBox dst)
        {
            if (!this._buffer.Contains(srcBox))
            {
                throw new ArgumentOutOfRangeException("source boux out of range");
            }

            if (srcBox.Left == 0 && srcBox.Right == Width && srcBox.Top == 0 && srcBox.Bottom == Height && srcBox.Front == 0 && srcBox.Back == Depth && dst.Width == Width && dst.Height == Height && dst.Depth == Depth && GLESPixelUtil.GetGLOriginFormat(dst.Format) != 0)
            {
                // The direct case: the user wants the entire texture in a format supported by GL
                // so we don't need an intermediate buffer
                Download(dst);
            }
            else
            {
                // Use buffer for intermediate copy
                AllocateBuffer();
                //download entire buffer
                Download(this._buffer);
                if (srcBox.Width != dst.Width || srcBox.Height != dst.Height || srcBox.Depth != dst.Depth)
                {
                    // we need scaling
                    Image.Scale(this._buffer.GetSubVolume(srcBox), dst, ImageFilter.Bilinear);
                }
                else
                {
                    // Just copy the bit that we need
                    PixelConverter.BulkPixelConversion(this._buffer.GetSubVolume(srcBox), dst);
                }
                FreeBuffer();
            }
        }
Esempio n. 2
0
        public void Blit(ref PixelBox src, BasicBox dstBox)
        {
            var srcBox = src;

            if (srcBox.Width != dstBox.Width || srcBox.Height != dstBox.Height)
            {
                // we need to rescale src to dst size first (also confvert format)
                var tmpData = new float[dstBox.Width * dstBox.Height];
                srcBox = new PixelBox(dstBox.Width, dstBox.Height, 1, PixelFormat.L8, BufferBase.Wrap(tmpData, tmpData.Length * sizeof(float)));
                Image.Scale(src, srcBox);
            }

            //pixel conversion
            var dstMemBox = new PixelBox(dstBox.Width, dstBox.Height, dstBox.Depth, PixelFormat.L8, BufferBase.Wrap(this.mData, mData.Length * sizeof(float)));

            PixelConverter.BulkPixelConversion(src, dstMemBox);

            if (srcBox != src)
            {
                // free temp
                srcBox = null;
            }
            var dRect = new Rectangle(dstBox.Left, dstBox.Top, dstBox.Right, dstBox.Bottom);

            DirtyRect(dRect);
        }
Esempio n. 3
0
        /// <summary>
        /// </summary>
        /// <param name="src"> </param>
        /// <param name="dstBox"> </param>
        public override void BlitFromMemory(PixelBox src, Media.BasicBox dstBox)
        {
            if (!this._buffer.Contains(dstBox))
            {
                throw new ArgumentOutOfRangeException("Destination box out of range, GLESHardwarePixelBuffer.BlitToMemory");
            }

            PixelBox scaled;

            if (src.Width != dstBox.Width || src.Height != dstBox.Height || src.Depth != dstBox.Depth)
            {
                LogManager.Instance.Write("[GLESHardwarePixelBuffer] Scale to destination size.");
                // Scale to destination size. Use DevIL and not iluScale because ILU screws up for
                // floating point textures and cannot cope with 3D images.
                // This also does pixel format conversion if needed
                AllocateBuffer();
                scaled = this._buffer.GetSubVolume(dstBox);
                Image.Scale(src, scaled, ImageFilter.Bilinear);
            }
            else if ((src.Format != Format) || ((GLESPixelUtil.GetGLOriginFormat(src.Format) == 0) && (src.Format != PixelFormat.R8G8B8)))
            {
                LogManager.Instance.Write("[GLESHardwarePixelBuffer] Extents match, but format is not accepted as valid source format for GL.");
                LogManager.Instance.Write("[GLESHardwarePixelBuffer] Source.Format = {0}, Format = {1}, GLOriginFormat = {2}", src.Format, Format, GLESPixelUtil.GetGLOriginFormat(src.Format));
                // Extents match, but format is not accepted as valid source format for GL
                // do conversion in temporary buffer
                AllocateBuffer();
                scaled = this._buffer.GetSubVolume(dstBox);

                PixelConverter.BulkPixelConversion(src, scaled);
            }
            else
            {
                LogManager.Instance.Write("[GLESHardwarePixelBuffer] No scaling or conversion needed.");
                scaled = src;
                if (src.Format == PixelFormat.R8G8B8)
                {
                    scaled.Format = PixelFormat.R8G8B8;
                    PixelConverter.BulkPixelConversion(src, scaled);
                }
                // No scaling or conversion needed
                // Set extents for upload
                scaled.Left   = dstBox.Left;
                scaled.Right  = dstBox.Right;
                scaled.Top    = dstBox.Top;
                scaled.Bottom = dstBox.Bottom;
                scaled.Front  = dstBox.Front;
                scaled.Back   = dstBox.Back;
            }

            Upload(scaled, dstBox);
            FreeBuffer();
        }
Esempio n. 4
0
        ///<summary>
        ///    Copies a region from normal memory to a region of this pixelbuffer. The source
        ///    image can be in any pixel format supported by Axiom, and in any size.
        ///</summary>
        ///<param name="src">PixelBox containing the source pixels and format in memory</param>
        ///<param name="dstBox">Image.BasicBox describing the destination region in this buffer</param>
        ///<remarks>
        ///    The source and destination regions dimensions don't have to match, in which
        ///    case scaling is done. This scaling is generally done using a bilinear filter in hardware,
        ///    but it is faster to pass the source image in the right dimensions.
        ///    Only call this function when both buffers are unlocked.
        ///</remarks>
        public override void BlitFromMemory(PixelBox src, BasicBox dstBox)
        {
            var converted   = src;
            var bufGCHandle = new GCHandle();
            var bufSize     = 0;

            // Get src.Data as byte[]
            bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, Format);
            var newBuffer = new byte[bufSize];

            //bufGCHandle = GCHandle.Alloc( newBuffer, GCHandleType.Pinned );
            //XnaHelper.Convert(XFG.SurfaceFormat) would never have returned SurfaceFormat.Unknown anyway...
            //if (XnaHelper.Convert(src.Format) != XFG.SurfaceFormat.Unknown)
            {
                converted = new PixelBox(src.Width, src.Height, src.Depth, Format, BufferBase.Wrap(newBuffer));
                PixelConverter.BulkPixelConversion(src, converted);
            }
            //else
            //{
            //    Memory.Copy(converted.Data, BufferBase.Wrap(newBuffer), bufSize);
            //}

            if (surface != null)
            {
                surface.SetData(mipLevel, XnaHelper.ToRectangle(dstBox), newBuffer, 0, bufSize);
            }
            else if (cube != null)
            {
                cube.SetData(face, mipLevel, XnaHelper.ToRectangle(dstBox), newBuffer, 0, bufSize);
            }
            else
            {
                throw new NotSupportedException("BlitFromMemory on Volume Textures not supported.");
            }

            // If we allocated a buffer for the temporary conversion, free it here
            if (bufGCHandle.IsAllocated)
            {
                bufGCHandle.Free();
            }

            if (doMipmapGen)
            {
                GenMipmaps();
            }
        }
Esempio n. 5
0
        public override void BlitFromMemory(Media.PixelBox src, Media.BasicBox dstBox)
        {
            if (this.Buffer.Contains(dstBox) == false)
            {
                throw new ArgumentOutOfRangeException("dstBox", "Destination box out of range");
            }

            PixelBox scaled;

            if (src.Width != dstBox.Width || src.Height != dstBox.Height || src.Depth != dstBox.Depth)
            {
                //Scale to destination size
                //This also does pixel format conversion if needed
                this.AllocateBuffer();
                scaled = this.Buffer.GetSubVolume(dstBox);
                Image.Scale(src, scaled, ImageFilter.Bilinear);
            }
            else if ((src.Format != format) || ((GLES2PixelUtil.GetGLOriginFormat(src.Format) == 0) && (src.Format != PixelFormat.R8G8B8)))
            {
                //Extents match, but format is not accepted as valid source format for GL
                //do conversion in temporary buffer
                this.AllocateBuffer();
                scaled = this.Buffer.GetSubVolume(dstBox);
                PixelConverter.BulkPixelConversion(src, scaled);
                if (src.Format == PixelFormat.A4R4G4B4)
                {
                    // ARGB->BGRA
                    GLES2PixelUtil.ConvertToGLFormat(ref scaled, ref scaled);
                }
            }
            else
            {
                this.AllocateBuffer();
                scaled = src.Clone();

                if (src.Format == PixelFormat.R8G8B8)
                {
                    scaled.Format = PixelFormat.B8G8R8;
                    PixelConverter.BulkPixelConversion(src, scaled);
                }
            }

            this.Upload(scaled, dstBox);
            this.FreeBuffer();
        }
Esempio n. 6
0
        public override void BlitFromMemory(PixelBox src, BasicBox dstBox)
        {
            PixelBox scaled;

            if (!this._buffer.Contains(dstBox))
            {
                throw new ArgumentException("Destination box out of range.");
            }

            if (src.Width != dstBox.Width || src.Height != dstBox.Height || src.Depth != dstBox.Depth)
            {
                // Scale to destination size. Use DevIL and not iluScale because ILU screws up for
                // floating point textures and cannot cope with 3D images.
                // This also does pixel format conversion if needed
                allocateBuffer();
                scaled = this._buffer.GetSubVolume(dstBox);

                Image.Scale(src, scaled, ImageFilter.Bilinear);
            }
            else if (GLPixelUtil.GetGLOriginFormat(src.Format) == 0)
            {
                // Extents match, but format is not accepted as valid source format for GL
                // do conversion in temporary buffer
                allocateBuffer();
                scaled = this._buffer.GetSubVolume(dstBox);
                PixelConverter.BulkPixelConversion(src, scaled);
            }
            else
            {
                // No scaling or conversion needed
                scaled = src;
                // Set extents for upload
                scaled.Left   = dstBox.Left;
                scaled.Right  = dstBox.Right;
                scaled.Top    = dstBox.Top;
                scaled.Bottom = dstBox.Bottom;
                scaled.Front  = dstBox.Front;
                scaled.Back   = dstBox.Back;
            }

            upload(scaled);
            freeBuffer();
        }
Esempio n. 7
0
        public virtual void Blit(HardwarePixelBuffer src, BasicBox srcBox, BasicBox dstBox)
        {
            if (IsLocked || src.IsLocked)
            {
                throw new AxiomException("Source and destination buffer may not be locked!");
            }

            if (src == this)
            {
                throw new AxiomException("Source must not be the same object.");
            }

            var srclock = src.Lock(srcBox, BufferLocking.ReadOnly);

            var method = BufferLocking.Normal;

            if (dstBox.Left == 0 && dstBox.Top == 0 && dstBox.Front == 0 && dstBox.Right == this.width &&
                dstBox.Bottom == this.height &&
                dstBox.Back == this.depth)
            {
                // Entire buffer -- we can discard the previous contents
                method = BufferLocking.Discard;
            }

            var dstlock = Lock(dstBox, method);

            if (dstlock.Width != srclock.Width || dstlock.Height != srclock.Height || dstlock.Depth != srclock.Depth)
            {
                // Scaling desired
                Image.Scale(srclock, dstlock);
            }
            else
            {
                // No scaling needed
                PixelConverter.BulkPixelConversion(srclock, dstlock);
            }

            Unlock();
            src.Unlock();
        }
Esempio n. 8
0
        private FI.FIBITMAP _encode(Stream input, CodecData codecData)
        {
            var ret = new FI.FIBITMAP();

            ret.SetNull();
            var imgData = codecData as ImageData;

            if (imgData != null)
            {
                var data = new byte[(int)input.Length];
                input.Read(data, 0, data.Length);
                var dataPtr = BufferBase.Wrap(data);
                var src     = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, dataPtr);

                // The required format, which will adjust to the format
                // actually supported by FreeImage.
                var requiredFormat = imgData.format;

                // determine the settings
                var imageType         = FI.FREE_IMAGE_TYPE.FIT_UNKNOWN;
                var determiningFormat = imgData.format;

                switch (determiningFormat)
                {
                case PixelFormat.R5G6B5:
                case PixelFormat.B5G6R5:
                case PixelFormat.R8G8B8:
                case PixelFormat.B8G8R8:
                case PixelFormat.A8R8G8B8:
                case PixelFormat.X8R8G8B8:
                case PixelFormat.A8B8G8R8:
                case PixelFormat.X8B8G8R8:
                case PixelFormat.B8G8R8A8:
                case PixelFormat.R8G8B8A8:
                case PixelFormat.A4L4:
                case PixelFormat.BYTE_LA:
                case PixelFormat.R3G3B2:
                case PixelFormat.A4R4G4B4:
                case PixelFormat.A1R5G5B5:
                case PixelFormat.A2R10G10B10:
                case PixelFormat.A2B10G10R10:
                    // I'd like to be able to use r/g/b masks to get FreeImage to load the data
                    // in it's existing format, but that doesn't work, FreeImage needs to have
                    // data in RGB[A] (big endian) and BGR[A] (little endian), always.
                    if (PixelUtil.HasAlpha(determiningFormat))
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGRA;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGBA;
                        }
                    }
                    else
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }
                    }
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L8:
                case PixelFormat.A8:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L16:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_UINT16;
                    break;

                case PixelFormat.SHORT_GR:
                    requiredFormat = PixelFormat.SHORT_RGB;
                    break;

                case PixelFormat.SHORT_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGB16;
                    break;

                case PixelFormat.SHORT_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBA16;
                    break;

                case PixelFormat.FLOAT16_R:
                    requiredFormat = PixelFormat.FLOAT32_R;
                    break;

                case PixelFormat.FLOAT32_R:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_FLOAT;
                    break;

                case PixelFormat.FLOAT16_GR:
                case PixelFormat.FLOAT16_RGB:
                case PixelFormat.FLOAT32_GR:
                    requiredFormat = PixelFormat.FLOAT32_RGB;
                    break;

                case PixelFormat.FLOAT32_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBF;
                    break;

                case PixelFormat.FLOAT16_RGBA:
                    requiredFormat = PixelFormat.FLOAT32_RGBA;
                    break;

                case PixelFormat.FLOAT32_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBAF;
                    break;

                default:
                    throw new AxiomException("Not Supported image format :{0}", determiningFormat.ToString());
                } //end switch

                // Check support for this image type & bit depth
                if (!FI.FreeImage.FIFSupportsExportType((FI.FREE_IMAGE_FORMAT) this._freeImageType, imageType) ||
                    !FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType,
                                                       PixelUtil.GetNumElemBits(requiredFormat)))
                {
                    // Ok, need to allocate a fallback
                    // Only deal with RGBA . RGB for now
                    switch (requiredFormat)
                    {
                    case PixelFormat.BYTE_RGBA:
                        requiredFormat = PixelFormat.BYTE_RGB;
                        break;

                    case PixelFormat.BYTE_BGRA:
                        requiredFormat = PixelFormat.BYTE_BGR;
                        break;

                    default:
                        break;
                    }
                }

                var conversionRequired = false;
                input.Position = 0;
                var srcData = new byte[(int)input.Length];
                input.Read(srcData, 0, srcData.Length);
                var srcDataPtr = BufferBase.Wrap(srcData);

                // Check BPP
                var bpp = PixelUtil.GetNumElemBits(requiredFormat);
                if (!FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, bpp))
                {
                    if (bpp == 32 && PixelUtil.HasAlpha(imgData.format) &&
                        FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 24))
                    {
                        // drop to 24 bit (lose alpha)
                        if (FI.FreeImage.IsLittleEndian())
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }

                        bpp = 24;
                    }
                    else if (bpp == 128 && PixelUtil.HasAlpha(imgData.format) &&
                             FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 96))
                    {
                        // drop to 96-bit floating point
                        requiredFormat = PixelFormat.FLOAT32_RGB;
                    }
                }

                var convBox = new PixelBox(imgData.width, imgData.height, 1, requiredFormat);
                if (requiredFormat != imgData.format)
                {
                    conversionRequired = true;
                    // Allocate memory
                    var convData = new byte[convBox.ConsecutiveSize];
                    convBox.Data = BufferBase.Wrap(convData);
                    // perform conversion and reassign source
                    var newSrc = new PixelBox(imgData.width, imgData.height, 1, imgData.format, dataPtr);
                    PixelConverter.BulkPixelConversion(newSrc, convBox);
                    srcDataPtr = convBox.Data;
                }

                ret = FI.FreeImage.AllocateT(imageType, imgData.width, imgData.height, bpp);
                if (ret.IsNull)
                {
                    if (conversionRequired)
                    {
                        srcDataPtr.SafeDispose();
                        convBox = null;
                    }

                    throw new AxiomException("FreeImage.AllocateT failed - possibly out of memory. ");
                }

                if (requiredFormat == PixelFormat.L8 || requiredFormat == PixelFormat.A8)
                {
                    // Must explicitly tell FreeImage that this is greyscale by setting
                    // a "grey" palette (otherwise it will save as a normal RGB
                    // palettized image).
                    var tmp = FI.FreeImage.ConvertToGreyscale(ret);
                    FI.FreeImage.Unload(ret);
                    ret = tmp;
                }

                var dstPitch = (int)FI.FreeImage.GetPitch(ret);
                var srcPitch = imgData.width * PixelUtil.GetNumElemBytes(requiredFormat);

                // Copy data, invert scanlines and respect FreeImage pitch
                var pSrc = srcDataPtr;
                using (var pDest = BufferBase.Wrap(FI.FreeImage.GetBits(ret), imgData.height * srcPitch))
                {
                    var byteSrcData = pSrc;
                    var byteDstData = pDest;
                    for (var y = 0; y < imgData.height; ++y)
                    {
                        byteSrcData += (imgData.height - y - 1) * srcPitch;
                        Memory.Copy(pSrc, pDest, srcPitch);
                        byteDstData += dstPitch;
                    }
                }

                if (conversionRequired)
                {
                    // delete temporary conversion area
                    srcDataPtr.SafeDispose();
                    convBox = null;
                }
            }
            return(ret);
        }
Esempio n. 9
0
        public virtual void LoadImages(Image[] images)
        {
            if (images.Length < 1)
            {
                throw new AxiomException("Cannot load empty vector of images");
            }

            // Set desired texture size and properties from images[0]
            this.srcWidth  = this.width = images[0].Width;
            this.srcHeight = this.height = images[0].Height;
            this.srcDepth  = this.depth = images[0].Depth;

            // Get source image format and adjust if required
            this.srcFormat = images[0].Format;
            if (this.treatLuminanceAsAlpha && this.srcFormat == PixelFormat.L8)
            {
                this.srcFormat = PixelFormat.A8;
            }

            if (this.desiredFormat != PixelFormat.Unknown)
            {
                // If have desired format, use it
                this.format = this.desiredFormat;
            }
            else
            {
                // Get the format according with desired bit depth
                this.format = PixelUtil.GetFormatForBitDepths(this.srcFormat, this.desiredIntegerBitDepth,
                                                              this.desiredFloatBitDepth);
            }

            // The custom mipmaps in the image have priority over everything
            var imageMips = images[0].NumMipMaps;

            if (imageMips > 0)
            {
                this.mipmapCount = this.requestedMipmapCount = imageMips;
                // Disable flag for auto mip generation
                this.usage &= ~TextureUsage.AutoMipMap;
            }

            // Create the texture
            CreateInternalResources();

            // Check if we're loading one image with multiple faces
            // or a vector of images representing the faces
            int  faces;
            bool multiImage;             // Load from multiple images?

            if (images.Length > 1)
            {
                faces      = images.Length;
                multiImage = true;
            }
            else
            {
                faces      = images[0].NumFaces;
                multiImage = false;
            }

            // Check wether number of faces in images exceeds number of faces
            // in this texture. If so, clamp it.
            if (faces > FaceCount)
            {
                faces = FaceCount;
            }

            // Say what we're doing
            if (TextureManager.Instance.Verbose)
            {
                var msg = new StringBuilder();
                msg.AppendFormat("Texture: {0}: Loading {1} faces( {2}, {3}x{4}x{5} ) with", _name, faces,
                                 PixelUtil.GetFormatName(images[0].Format), images[0].Width, images[0].Height,
                                 images[0].Depth);
                if (!(this.mipmapsHardwareGenerated && this.mipmapCount == 0))
                {
                    msg.AppendFormat(" {0}", this.mipmapCount);
                }

                if ((this.usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap)
                {
                    msg.AppendFormat("{0} generated mipmaps", this.mipmapsHardwareGenerated ? " hardware" : string.Empty);
                }
                else
                {
                    msg.Append(" custom mipmaps");
                }

                msg.AppendFormat(" from {0}.\n\t", multiImage ? "multiple Images" : "an Image");

                // Print data about first destination surface
                var buf = GetBuffer(0, 0);
                msg.AppendFormat(" Internal format is {0} , {1}x{2}x{3}.", PixelUtil.GetFormatName(buf.Format), buf.Width,
                                 buf.Height, buf.Depth);

                LogManager.Instance.Write(msg.ToString());
            }

            // Main loading loop
            // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
            for (var mip = 0; mip <= imageMips; ++mip)
            {
                for (var i = 0; i < faces; ++i)
                {
                    PixelBox src;
                    if (multiImage)
                    {
                        // Load from multiple images
                        src = images[i].GetPixelBox(0, mip);
                    }
                    else
                    {
                        // Load from faces of images[0]
                        src = images[0].GetPixelBox(i, mip);
                    }

                    // Sets to treated format in case is difference
                    src.Format = this.srcFormat;

                    if (this.gamma != 1.0f)
                    {
                        // Apply gamma correction
                        // Do not overwrite original image but do gamma correction in temporary buffer
                        var bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format);
                        var buff    = new byte[bufSize];
                        var buffer  = BufferBase.Wrap(buff);

                        var corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer);
                        PixelConverter.BulkPixelConversion(src, corrected);

                        Image.ApplyGamma(corrected.Data, this.gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format));

                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(corrected);
                    }
                    else
                    {
                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(src);
                    }
                }
            }

            // Update size (the final size, not including temp space)
            Size = FaceCount * PixelUtil.GetMemorySize(this.width, this.height, this.depth, this.format);
        }
Esempio n. 10
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();
            }
        }
Esempio n. 11
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);
            }
        }
Esempio n. 12
0
        public override void CopyContentsToMemory(PixelBox dst, FrameBuffer buffer)
        {
            if ((dst.Left < 0) || (dst.Right > Width) ||
                (dst.Top < 0) || (dst.Bottom > Height) ||
                (dst.Front != 0) || (dst.Back != 1))
            {
                throw new Exception("Invalid box.");
            }

            var device = Driver.XnaDevice;
            //in 3.1, this was ResolveTexture2D, an actual RenderTarget provides the exact same
            //functionality, especially seeing as RenderTarget2D is a texture now.
            //the difference is surface is actually set on the device -DoubleA
            RenderTarget2D surface;
            var            data  = new byte[dst.ConsecutiveSize];
            var            pitch = 0;

            if (buffer == FrameBuffer.Auto)
            {
                buffer = FrameBuffer.Front;
            }

#if SILVERLIGHT
            var mode = ((XnaRenderSystem)Root.Instance.RenderSystem).DisplayMode;
            surface = new RenderTarget2D(device, mode.Width, mode.Height, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);
#else
            var mode = device.DisplayMode;
            surface = new RenderTarget2D(device, mode.Width, mode.Height, false, SurfaceFormat.Rgba64, DepthFormat.Depth24Stencil8);
#endif
            //ResolveTexture2D( device, mode.Width, mode.Height, 0, SurfaceFormat.Rgba32 );

#if !SILVERLIGHT
            if (buffer == FrameBuffer.Front)
            {
                // get the entire front buffer.  This is SLOW!!
                device.SetRenderTarget(surface);

                if (IsFullScreen)
                {
                    if ((dst.Left == 0) && (dst.Right == Width) && (dst.Top == 0) && (dst.Bottom == Height))
                    {
                        surface.GetData(data);
                    }
                    else
                    {
                        var rect = new Rectangle();
                        rect.Left   = dst.Left;
                        rect.Right  = dst.Right;
                        rect.Top    = dst.Top;
                        rect.Bottom = dst.Bottom;

                        surface.GetData(0, XnaHelper.ToRectangle(rect), data, 0, 255);
                    }
                }
#if !(XBOX || XBOX360 || WINDOWS_PHONE)
                else
                {
                    var srcRect = new Rectangle();
                    srcRect.Left   = dst.Left;
                    srcRect.Right  = dst.Right;
                    srcRect.Top    = dst.Top;
                    srcRect.Bottom = dst.Bottom;
                    // Adjust Rectangle for Window Menu and Chrome
                    var point = new Point();
                    point.X = (int)srcRect.Left;
                    point.Y = (int)srcRect.Top;
                    var control = Control.FromHandle(_windowHandle);
                    point           = control.PointToScreen(point);
                    srcRect.Top     = (long)point.Y;
                    srcRect.Left    = (long)point.X;
                    srcRect.Bottom += (long)point.Y;
                    srcRect.Right  += (long)point.X;

                    surface.GetData(0, XnaHelper.ToRectangle(srcRect), data, 0, 255);
                }
#endif
            }
            else
            {
                device.SetRenderTarget(surface);

                if ((dst.Left == 0) && (dst.Right == Width) && (dst.Top == 0) && (dst.Bottom == Height))
                {
                    surface.GetData(data);
                }
                else
                {
                    var rect = new Rectangle();
                    rect.Left   = dst.Left;
                    rect.Right  = dst.Right;
                    rect.Top    = dst.Top;
                    rect.Bottom = dst.Bottom;

                    surface.GetData(0, XnaHelper.ToRectangle(rect), data, 0, 255);
                }
            }
#endif

            var format = XnaHelper.Convert(surface.Format);

            if (format == PixelFormat.Unknown)
            {
                throw new Exception("Unsupported format");
            }

            var dataPtr = Memory.PinObject(data);
            var src     = new PixelBox(dst.Width, dst.Height, 1, format, dataPtr);
            src.RowPitch   = pitch / PixelUtil.GetNumElemBytes(format);
            src.SlicePitch = surface.Height * src.RowPitch;

            PixelConverter.BulkPixelConversion(src, dst);

            Memory.UnpinObject(data);
            surface.Dispose();
        }
Esempio n. 13
0
        public override void BlitFromMemory(PixelBox src, BasicBox dstBox)
        {
            // Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case
            // - FBO is not supported
            // - Either source or target is luminance due doesn't looks like supported by hardware
            // - the source dimensions match the destination ones, in which case no scaling is needed
            //Ogre TODO: Check that extension is NOT available
            if (PixelUtil.IsLuminance(src.Format) || PixelUtil.IsLuminance(this.format) || (src.Width == dstBox.Width && src.Height == dstBox.Height && src.Depth == dstBox.Depth))
            {
                base.BlitFromMemory(src, dstBox);
                return;
            }

            if (!Buffer.Contains(dstBox))
            {
                throw new ArgumentOutOfRangeException("dstBox", "Destination box out of range");
            }

            //For scoped deletion of conversion buffer

            PixelBox   srcPB;
            BufferBase buf;

            //first, convert the srcbox to a OpenGL compatible pixel format
            if (GLES2PixelUtil.GetGLOriginFormat(src.Format) == 0)
            {
                //Conver to buffer intenral format
                buf = BufferBase.Wrap(new byte[PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, this.format)]);

                srcPB = new PixelBox(src.Width, src.Height, src.Depth, this.format, buf);
                PixelConverter.BulkPixelConversion(src, srcPB);
            }
            else
            {
                //No conversion needed
                srcPB = src;
            }

            //Create temporary texture to store source data
            int id       = 0;
            All target   = All.Texture2D;
            int width    = GLES2PixelUtil.OptionalPO2(src.Width);
            int height   = GLES2PixelUtil.OptionalPO2(src.Height);
            All format   = GLES2PixelUtil.GetClosestGLInternalFormat(src.Format);
            All datatype = GLES2PixelUtil.GetGLOriginDataType(src.Format);

            //Generate texture name
            GL.GenTextures(1, ref id);
            GLES2Config.GlCheckError(this);

            //Set texture type
            GL.BindTexture(target, id);
            GLES2Config.GlCheckError(this);

            //Allocate texture memory
            GL.TexImage2D(target, 0, (int)format, width, height, 0, format, datatype, IntPtr.Zero);
            GLES2Config.GlCheckError(this);

            var tex = new GLES2TextureBuffer(string.Empty, target, id, width, height, format, (All)src.Format, 0, 0, BufferUsage.StaticWriteOnly, false, false, 0);

            //Upload data to 0,0,0 in temprary texture
            var tempTarget = new BasicBox(0, 0, 0, srcPB.Width, srcPB.Height, srcPB.Depth);

            tex.Upload(srcPB, tempTarget);

            //Blit
            this.BlitFromTexture(tex, tempTarget, dstBox);
            GLES2Config.GlCheckError(this);
        }
Esempio n. 14
0
        public static void ConvertToIL(PixelBox src)
        {
            // ilTexImage http://openil.sourceforge.net/docs/il/f00059.htm
            var ifmt = Convert(src.Format);

            if (src.IsConsecutive && ifmt.IsValid)
            {
                // The easy case, the buffer is laid out in memory just like
                // we want it to be and is in a format DevIL can understand directly
                // We could even save the copy if DevIL would let us
                Il.ilTexImage(src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, src.Data.Pin());
                src.Data.UnPin();
            }
            else if (ifmt.IsValid)
            {
                // The format can be understood directly by DevIL. The only
                // problem is that ilTexImage expects our image data consecutively
                // so we cannot use that directly.

                // Let DevIL allocate the memory for us, and copy the data consecutively
                // to its memory
                Il.ilTexImage(src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, IntPtr.Zero);
                using (var dstbuf = BufferBase.Wrap(Il.ilGetData(), Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA)))
                {
                    var dst = new PixelBox(src.Width, src.Height, src.Depth, src.Format, dstbuf);
                    PixelConverter.BulkPixelConversion(src, dst);
                }
            }
            else
            {
                // Here it gets ugly. We're stuck with a pixel format that DevIL
                // can't do anything with. We will do a bulk pixel conversion and
                // then feed it to DevIL anyway. The problem is finding the best
                // format to convert to.

                // most general format supported by Axiom and DevIL
                var fmt = PixelUtil.HasAlpha(src.Format) ? PixelFormat.FLOAT32_RGBA : PixelFormat.FLOAT32_RGB;

                // Make up a pixel format
                // We don't have to consider luminance formats as they have
                // straight conversions to DevIL, just weird permutations of RGBA an LA
                var depths = PixelUtil.GetBitDepths(src.Format);

                // Native endian format with all bit depths<8 can safely and quickly be
                // converted to 24/32 bit
                if (PixelUtil.IsNativeEndian(src.Format) && depths[0] <= 8 && depths[1] <= 8 && depths[2] <= 8 &&
                    depths[3] <= 8)
                {
                    if (PixelUtil.HasAlpha(src.Format))
                    {
                        fmt = PixelFormat.A8R8G8B8;
                    }
                    else
                    {
                        fmt = PixelFormat.R8G8B8;
                    }
                }

                // Let DevIL allocate the memory for us, then do the conversion ourselves
                ifmt = Convert(fmt);
                Il.ilTexImage(src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, IntPtr.Zero);
                // TAO 2.0
                //Il.ilTexImage( src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, null );
                using (var dstbuf = BufferBase.Wrap(Il.ilGetData(), Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA)))
                {
                    var dst = new PixelBox(src.Width, src.Height, src.Depth, fmt, dstbuf);
                    PixelConverter.BulkPixelConversion(src, dst);
                }
            }
        }
Esempio n. 15
0
        public static void ConvertFromIL(PixelBox dst)
        {
            if (!dst.IsConsecutive)
            {
                throw new NotImplementedException("Destination must currently be consecutive");
            }

            if (dst.Width != Il.ilGetInteger(Il.IL_IMAGE_WIDTH) || dst.Height != Il.ilGetInteger(Il.IL_IMAGE_HEIGHT) ||
                dst.Depth != Il.ilGetInteger(Il.IL_IMAGE_DEPTH))
            {
                throw new AxiomException("Destination dimensions must equal IL dimension");
            }

            var ilfmt = Il.ilGetInteger(Il.IL_IMAGE_FORMAT);
            var iltp  = Il.ilGetInteger(Il.IL_IMAGE_TYPE);

            // Check if in-memory format just matches
            // If yes, we can just copy it and save conversion
            var ifmt = Convert(dst.Format);

            if (ifmt.Format == ilfmt && _iLabs(ifmt.Type) == _iLabs(iltp))
            {
                var size = Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA);
                using (var src = BufferBase.Wrap(Il.ilGetData(), size))
                {
                    Memory.Copy(src, dst.Data, size);
                }
                return;
            }

            // Try if buffer is in a known Axiom format so we can use its conversion routines
            var bufFmt = Convert((int)ilfmt, (int)iltp);

            ifmt = Convert(bufFmt);

            if (ifmt.Format == ilfmt && _iLabs(ifmt.Type) == _iLabs(iltp))
            {
                using (var dstbuf = BufferBase.Wrap(Il.ilGetData(), Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA)))
                {
                    // IL format matches another Axiom format
                    var src = new PixelBox(dst.Width, dst.Height, dst.Depth, bufFmt, dstbuf);
                    PixelConverter.BulkPixelConversion(src, dst);
                }
                return;
            }

            // Thee extremely slow method
            if (iltp == Il.IL_UNSIGNED_BYTE || iltp == Il.IL_BYTE)
            {
                _ilToAxiomInternal <byte>(dst.Data, dst.Format, 0x00, 0x00, 0x00, 0xFF);
            }
            else if (iltp == Il.IL_FLOAT)
            {
                _ilToAxiomInternal <float>(dst.Data, dst.Format, 0.0f, 0.0f, 0.0f, 1.0f);
            }
            else if (iltp == Il.IL_SHORT || iltp == Il.IL_UNSIGNED_SHORT)
            {
                _ilToAxiomInternal <ushort>(dst.Data, dst.Format, 0x0000, 0x0000, 0x0000, 0xFFFF);
            }
            else
            {
                throw new NotImplementedException("Cannot convert this DevIL type.");
            }
        }