/// <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(); } }
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); }
/// <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(); }
///<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(); } }
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(); }
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(); }
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(); }
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); }
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); }
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(); } }
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); } }
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(); }
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); }
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); } } }
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."); } }