public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer) { Debug.Assert((offset + length) <= base.sizeInBytes); using (var pIntData = BufferBase.Wrap(_mpData, length).Offset(offset)) Memory.Copy(src, pIntData, length); }
/// <summary> /// /// </summary> /// <param name="val"></param> /// <param name="offset"></param> /// <param name="count"></param> public void Write(System.Array val, int offset, int count) { // can't write to unlocked buffers if (!this.owner.IsLocked) { throw new AxiomException("Cannot write to a buffer stream when the buffer is not locked."); } var newOffset = this.position + offset; // ensure we won't go past the end of the stream if (newOffset + count > Length) { throw new AxiomException("Unable to write data past the end of a BufferStream"); } // pin the array so we can get a pointer to it using (var handle = BufferBase.Wrap(val, count)) { #if !AXIOM_SAFE_ONLY unsafe #endif { // get byte pointers for the source and target var b = handle.ToBytePointer(); var dataPtr = this.data.ToBytePointer(); // copy the data from the source to the target for (var i = 0; i < count; i++) { dataPtr[(int)(i + newOffset)] = b[i]; } } } }
protected static void FromD3DLock(PixelBox rval, DX.DataBox lbox) { var bpp = PixelUtil.GetNumElemBytes(rval.Format); var size = 0; if (bpp != 0) { rval.RowPitch = lbox.RowPitch / bpp; rval.SlicePitch = lbox.SlicePitch / bpp; Debug.Assert((lbox.RowPitch % bpp) == 0); Debug.Assert((lbox.SlicePitch % bpp) == 0); size = lbox.RowPitch * rval.Height; } else if (PixelUtil.IsCompressed(rval.Format)) { rval.RowPitch = rval.Width; rval.SlicePitch = rval.Width * rval.Height; size = rval.Width * rval.Height; } else { throw new AxiomException("Invalid pixel format"); } rval.Data = BufferBase.Wrap(lbox.DataPointer, size); }
public override void ReadData(int offset, int length, BufferBase dest) { Debug.Assert((offset + length) <= base.sizeInBytes); using (var data = BufferBase.Wrap(_mpData).Offset(offset)) Memory.Copy(dest, data, length); }
///<summary> /// Internal implementation of <see cref="HardwareBuffer.Lock"/>. ///</summary> protected override PixelBox LockImpl(BasicBox lockBox, BufferLocking options) { _lockedBox = lockBox; // Set extents and format var rval = new PixelBox(lockBox, Format); var sizeInBytes = PixelUtil.GetMemorySize(lockBox.Width, lockBox.Height, lockBox.Depth, XnaHelper.Convert(surface.Format)); if (_bufferBytes == null || _bufferBytes.Length != sizeInBytes) { _bufferBytes = new byte[sizeInBytes]; #if !SILVERLIGHT if (surface != null) { surface.GetData(mipLevel, XnaHelper.ToRectangle(lockBox), _bufferBytes, 0, _bufferBytes.Length); } else if (cube != null) { cube.GetData(face, mipLevel, XnaHelper.ToRectangle(lockBox), _bufferBytes, 0, _bufferBytes.Length); } else { volume.GetData(mipLevel, lockBox.Left, lockBox.Top, lockBox.Right, lockBox.Bottom, lockBox.Front, lockBox.Back, _bufferBytes, 0, _bufferBytes.Length); } #endif } rval.Data = BufferBase.Wrap(_bufferBytes); return(rval); }
public override Stream Encode(Stream input, Codec.CodecData pData) { var fiBitmap = _encode(input, pData); // open memory chunk allocated by FreeImage var mem = FI.FreeImage.OpenMemory(IntPtr.Zero, 0); // write data into memory FI.FreeImage.SaveToMemory((FI.FREE_IMAGE_FORMAT) this._freeImageType, fiBitmap, mem, FI.FREE_IMAGE_SAVE_FLAGS.DEFAULT); // Grab data information var data = IntPtr.Zero; uint size = 0; FI.FreeImage.AcquireMemory(mem, ref data, ref size); // Copy data into our own buffer // Because we're asking MemoryDataStream to free this, must create in a compatible way var ourData = new byte[size]; using (var src = BufferBase.Wrap(data, (int)size)) { using (var dest = BufferBase.Wrap(ourData)) { Memory.Copy(src, dest, (int)size); } } // Wrap data in stream, tell it to free on close var outstream = new MemoryStream(ourData); // Now free FreeImage memory buffers FI.FreeImage.CloseMemory(mem); // Unload bitmap FI.FreeImage.Unload(fiBitmap); return(outstream); }
protected void Download() { #if !AXIOM_SAFE_ONLY unsafe #endif { using (var pDst = BufferBase.Wrap(this.mData, mData.Length * sizeof(float))) { var pDstPtr = pDst.ToFloatPointer(); var pDstIdx = 0; //download data var box = new BasicBox(0, 0, this.mBuffer.Width, this.mBuffer.Height); var pBox = this.mBuffer.Lock(box, BufferLocking.ReadOnly); var pSrc = pBox.Data.ToBytePointer(); var pSrcIdx = (int)this.mChannelOffset; var srcInc = PixelUtil.GetNumElemBytes(this.mBuffer.Format); for (var y = box.Top; y < box.Bottom; ++y) { for (var x = box.Left; x < box.Right; ++x) { pDstPtr[pDstIdx++] = (float)((pSrc[pSrcIdx]) / 255.0f); pSrcIdx += srcInc; } } this.mBuffer.Unlock(); } } }
/// <summary> /// /// </summary> /// <param name="offset"></param> /// <param name="length"></param> /// <param name="locking"></param> /// <returns></returns> protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { _offset = offset; _length = length; _locking = locking; return(BufferBase.Wrap(_bufferBytes).Offset(offset)); }
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."); } if (buffer == RenderTarget.FrameBuffer.Auto) { buffer = IsFullScreen ? RenderTarget.FrameBuffer.Front : RenderTarget.FrameBuffer.Back; } int format = GLPixelUtil.GetGLOriginFormat(dst.Format); int type = GLPixelUtil.GetGLOriginDataType(dst.Format); if ((format == Gl.GL_NONE) || (type == 0)) { throw new Exception("Unsupported format."); } // Switch context if different from current one RenderSystem rsys = Root.Instance.RenderSystem; rsys.Viewport = this.GetViewport(0); // Must change the packing to ensure no overruns! Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 1); Gl.glReadBuffer((buffer == RenderTarget.FrameBuffer.Front) ? Gl.GL_FRONT : Gl.GL_BACK); Gl.glReadPixels(dst.Left, dst.Top, dst.Width, dst.Height, format, type, dst.Data); // restore default alignment Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 4); //vertical flip { int rowSpan = dst.Width * PixelUtil.GetNumElemBytes(dst.Format); int height = dst.Height; byte[] tmpData = new byte[rowSpan * height]; unsafe { var dataPtr = dst.Data.ToBytePointer(); //int *srcRow = (uchar *)dst.data, *tmpRow = tmpData + (height - 1) * rowSpan; for (int row = height - 1, tmpRow = 0; row >= 0; row--, tmpRow++) { for (int col = 0; col < rowSpan; col++) { tmpData[tmpRow * rowSpan + col] = dataPtr[row * rowSpan + col]; } } } var tmpDataHandle = BufferBase.Wrap(tmpData); Memory.Copy(tmpDataHandle, dst.Data, rowSpan * height); } }
private void _unpackDXTColor(PixelFormat pf, DXTColorBlock block, ColorEx[] pCol) { // Note - we assume all values have already been endian swapped // Colour lookup table var derivedColours = new ColorEx[4]; using (var src = BufferBase.Wrap(block.colour_0, 1)) { derivedColours[0] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src); } using (var src = BufferBase.Wrap(block.colour_1, 1)) { derivedColours[1] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src); } if (pf == PixelFormat.DXT1 && block.colour_0 <= block.colour_1) { // 1-bit alpha // one intermediate colour, half way between the other two derivedColours[2] = (derivedColours[0] + derivedColours[1]) / 2; // transparent colour derivedColours[3] = new ColorEx(0, 0, 0, 0); } else { // first interpolated colour, 1/3 of the way along derivedColours[2] = (derivedColours[0] * 2 + derivedColours[1]) / 3; // second interpolated colour, 2/3 of the way along derivedColours[3] = (derivedColours[0] + derivedColours[1] * 2) / 3; } // Process 4x4 block of texels for (var row = 0; row < 4; ++row) { for (var x = 0; x < 4; ++x) { // LSB come first var colIdx = (byte)block.indexRow[row] >> (x * 2) & 0x3; if (pf == PixelFormat.DXT1) { // Overwrite entire colour pCol[(row * 4) + x] = derivedColours[colIdx]; } else { // alpha has already been read (alpha precedes colour) var col = pCol[(row * 4) + x]; col.r = derivedColours[colIdx].r; col.g = derivedColours[colIdx].g; col.b = derivedColours[colIdx].b; } } } }
private void AllocateBuffer() { if (this.Buffer.Data != null) { //already allocated return; } this.Buffer.Data = BufferBase.Wrap(new byte[sizeInBytes]); }
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(); }
private void BuildMipmaps(PixelBox data) { int width, height, logW, logH, level; PixelBox scaled = data; scaled.Data = data.Data; scaled.Left = data.Left; scaled.Right = data.Right; scaled.Top = data.Top; scaled.Bottom = data.Bottom; scaled.Front = data.Front; scaled.Back = data.Back; width = data.Width; height = data.Height; logW = (int)System.Math.Log(width); logH = (int)System.Math.Log(height); level = (logW > logH ? logW : logH); for (int mip = 0; mip < level; mip++) { All glFormat = GLES2PixelUtil.GetGLOriginFormat(scaled.Format); All dataType = GLES2PixelUtil.GetGLOriginDataType(scaled.Format); GL.TexImage2D(this.faceTarget, mip, (int)glFormat, width, height, 0, glFormat, dataType, scaled.Data.Pin()); GLES2Config.GlCheckError(this); if (mip != 0) { scaled.Data = null; } if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } int sizeInBytes = PixelUtil.GetMemorySize(width, height, 1, data.Format); scaled = new PixelBox(width, height, 1, data.Format); scaled.Data = BufferBase.Wrap(new byte[sizeInBytes]); Image.Scale(data, scaled, ImageFilter.Linear); } //Delete the scaled data for the last level if (level > 0) { scaled.Data = null; } }
/// <summary> /// </summary> /// <param name="idxType"> </param> /// <param name="numIndexes"> </param> /// <param name="usage"> </param> public GLESDefaultHardwareIndexBuffer(IndexType idxType, int numIndexes, BufferUsage usage) : base(null, idxType, numIndexes, usage, true, false) // always software, never shadowed { if (idxType == IndexType.Size32) { throw new AxiomException("32 bit hardware buffers are not allowed in OpenGL ES."); } this._data = new byte[sizeInBytes]; this._dataPtr = BufferBase.Wrap(this._data); }
public void WriteContentsToFile(string fileName) { var pf = SuggestPixelFormat(); var data = new byte[Width * Height * PixelUtil.GetNumElemBytes(pf)]; var buf = BufferBase.Wrap(data); var pb = new PixelBox(Width, Height, 1, pf, buf); CopyContentsToMemory(pb); (new Image()).FromDynamicImage(data, Width, Height, 1, pf, false, 1, 0).Save(fileName); buf.Dispose(); }
protected void SetBuffer(byte[] newBuffer) { if (this.buffer != null) { this.bufPtr = null; this.buffer = null; } if (newBuffer != null) { this.buffer = newBuffer; this.bufPtr = BufferBase.Wrap(newBuffer); } }
protected void allocateBuffer() { if (buffer.Data != null) { // Already allocated return; } // Allocate storage this._data = new byte[sizeInBytes]; buffer.Data = BufferBase.Wrap(this._data); // TODO: use PBO if we're HBU_DYNAMIC }
///<summary> ///</summary> ///<param name="offset"> </param> ///<param name="length"> </param> ///<param name="locking"> </param> ///<returns> </returns> protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { int access = 0; if (isLocked) { throw new Exception("Invalid attempt to lock an index buffer that has already been locked."); } // bind this buffer Gl.glBindBufferARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, this._bufferId); if (locking == BufferLocking.Discard) { // commented out to fix ATI issues /*Gl.glBufferDataARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, * sizeInBytes, * IntPtr.Zero, * GLHelper.ConvertEnum(usage)); */ // find out how we shall access this buffer access = (usage == BufferUsage.Dynamic) ? Gl.GL_READ_WRITE_ARB : Gl.GL_WRITE_ONLY_ARB; } else if (locking == BufferLocking.ReadOnly) { if (usage == BufferUsage.WriteOnly) { LogManager.Instance.Write("OGL : Invalid attempt to lock a write-only vertex buffer as read-only."); } access = Gl.GL_READ_ONLY_ARB; } else if (locking == BufferLocking.Normal || locking == BufferLocking.NoOverwrite) { access = (usage == BufferUsage.Dynamic) ? Gl.GL_READ_WRITE_ARB : Gl.GL_WRITE_ONLY_ARB; } IntPtr ptr = Gl.glMapBufferARB(Gl.GL_ELEMENT_ARRAY_BUFFER_ARB, access); if (ptr == IntPtr.Zero) { throw new Exception("OGL: Vertex Buffer: Out of memory"); } isLocked = true; return(BufferBase.Wrap(new IntPtr(ptr.ToInt64() + offset), length)); }
public override void EncodeToFile(Stream input, string outFileName, Codec.CodecData codecData) { int imageID; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); var buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); var imgData = (ImageData)codecData; PixelBox src; using (var bufHandle = BufferBase.Wrap(buffer)) { src = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, bufHandle); } try { // Convert image from Axiom to current IL image ILUtil.ConvertToIL(src); } catch (Exception ex) { LogManager.Instance.Write("IL Failed image conversion :", ex.Message); } // flip the image Ilu.iluFlipImage(); // save the image to file Il.ilSaveImage(outFileName); var error = Il.ilGetError(); if (error != Il.IL_NO_ERROR) { LogManager.Instance.Write("IL Error, could not save file: {0} : {1}", outFileName, Ilu.iluErrorString(error)); } Il.ilDeleteImages(1, ref imageID); }
///<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 string MagicNumberToFileExt(byte[] magicNumberBuf, int maxbytes) { if (maxbytes >= sizeof(int)) { var fileType = BitConverter.ToInt32(magicNumberBuf, 0); using (var data = BufferBase.Wrap(fileType, 2)) { _flipEndian(data, sizeof(int), 1); } if (this.PVR_MAGIC == fileType) { return("pvr"); } } return(string.Empty); }
public void Update() { if (this.mData != null && this.mDirty) { using (var mDataBuf = BufferBase.Wrap(this.mData, mData.Length * sizeof(float))) { var pSrcBase = mDataBuf + (this.mDirtyBox.Top * this.mBuffer.Width + this.mDirtyBox.Left); var pDstBase = this.mBuffer.Lock(this.mDirtyBox, BufferLocking.Normal).Data; pDstBase += this.mChannelOffset; var dstInc = PixelUtil.GetNumElemBytes(this.mBuffer.Format); #if !AXIOM_SAFE_ONLY unsafe #endif { for (int y = 0; y < this.mDirtyBox.Height; ++y) { var pSrc = (pSrcBase + (y * this.mBuffer.Width) * sizeof(float)).ToFloatPointer(); var pDst = pDstBase + (y * this.mBuffer.Width * dstInc); for (int x = 0; x < this.mDirtyBox.Width; ++x) { pDst.ToBytePointer()[0] = (byte)(pSrc[x] * 255); pDst += dstInc; } } } this.mBuffer.Unlock(); this.mDirty = false; } // make sure composite map is updated // mDirtyBox is in image space, convert to terrain units var compositeMapRect = new Rectangle(); var blendToTerrain = (float)this.mParent.Size / (float)this.mBuffer.Width; compositeMapRect.Left = (long)(this.mDirtyBox.Left * blendToTerrain); compositeMapRect.Right = (long)(this.mDirtyBox.Right * blendToTerrain + 1); compositeMapRect.Top = (long)((this.mBuffer.Height - this.mDirtyBox.Bottom) * blendToTerrain); compositeMapRect.Bottom = (long)((this.mBuffer.Height - this.mDirtyBox.Top) * blendToTerrain + 1); this.mParent.DirtyCompositeMapRect(compositeMapRect); this.mParent.UpdateCompositeMapWithDelay(); } }
/// <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); }
public override string MagicNumberToFileExt(byte[] magicBuf, int maxbytes) { FI.FIMEMORY fiMem; FI.FREE_IMAGE_FORMAT fif; using (var ptr = BufferBase.Wrap(magicBuf)) { fiMem = FI.FreeImage.OpenMemory(ptr.Pin(), (uint)maxbytes); ptr.UnPin(); fif = FI.FreeImage.GetFileTypeFromMemory(fiMem, maxbytes); FI.FreeImage.CloseMemory(fiMem); } if (fif != FI.FREE_IMAGE_FORMAT.FIF_UNKNOWN) { return(FI.FreeImage.GetFormatFromFIF(fif).ToLower()); } else { return(string.Empty); } }
public D3D9HardwareVertexBuffer(HardwareBufferManagerBase manager, VertexDeclaration vertexDeclaration, int numVertices, BufferUsage usage, bool useSystemMemory, bool useShadowBuffer) : base(manager, vertexDeclaration, numVertices, usage, useSystemMemory, useShadowBuffer) { //Entering critical section this.LockDeviceAccess(); this._mapDeviceToBufferResources = new Dictionary <D3D9.Device, BufferResources>(); #if AXIOM_D3D_MANAGE_BUFFERS var eResourcePool = useSystemMemory ? D3D9.Pool.SystemMemory : // If not system mem, use managed pool UNLESS buffer is discardable // if discardable, keeping the software backing is expensive ((usage & BufferUsage.Discardable) != 0) ? D3D9.Pool.Default : D3D9.Pool.Managed; #else var eResourcePool = useSystemMemory ? D3D9.Pool.SystemMemory : D3D9.Pool.Default; #endif // Set the desired memory pool. this._bufferDesc.Pool = eResourcePool; // Allocate the system memory buffer. this._systemMemoryBuffer = BufferBase.Wrap(new byte[sizeInBytes]); // Case we have to create this buffer resource on loading. if (D3D9RenderSystem.ResourceManager.CreationPolicy == D3D9ResourceManager.ResourceCreationPolicy.CreateOnAllDevices) { foreach (var d3d9Device in D3D9RenderSystem.ResourceCreationDevices) { CreateBuffer(d3d9Device, this._bufferDesc.Pool); } } D3D9RenderSystem.ResourceManager.NotifyResourceCreated(this); //Leaving critical section this.UnlockDeviceAccess(); }
/// <summary> /// </summary> /// <param name="offset"> </param> /// <param name="length"> </param> /// <param name="locking"> </param> /// <returns> </returns> protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { All access = 0; if (isLocked) { throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked"); } BufferBase retPtr = null; if (length < MapBufferThreshold) { retPtr = ((GLESHardwareBufferManager)HardwareBufferManager.Instance).AllocateScratch(length); if (retPtr != null) { this._lockedToScratch = true; this._scratchOffset = offset; this._scratchSize = length; this._scratchPtr = retPtr; this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly); if (locking != BufferLocking.Discard) { this.ReadData(offset, length, retPtr); } } } else { throw new AxiomException("Invalid Buffer lockSize"); } if (retPtr == null) { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLESConfig.GlCheckError(this); // Use glMapBuffer if (locking == BufferLocking.Discard) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) != 0) { access = All.WriteOnlyOes; } IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access); GLESConfig.GlCheckError(this); if (pBuffer == IntPtr.Zero) { throw new AxiomException("Index Buffer: Out of memory"); } unsafe { // return offset retPtr = BufferBase.Wrap(pBuffer, sizeInBytes); } this._lockedToScratch = false; } isLocked = true; return(retPtr); }
public override Codec.DecodeResult Decode(Stream input) { // Buffer stream into memory (TODO: override IO functions instead?) var data = new byte[(int)input.Length]; input.Read(data, 0, data.Length); FI.FIMEMORY fiMem; FI.FREE_IMAGE_FORMAT ff; FI.FIBITMAP fiBitmap; using (var datPtr = BufferBase.Wrap(data)) { fiMem = FI.FreeImage.OpenMemory(datPtr.Pin(), (uint)data.Length); datPtr.UnPin(); ff = (FI.FREE_IMAGE_FORMAT) this._freeImageType; fiBitmap = FI.FreeImage.LoadFromMemory((FI.FREE_IMAGE_FORMAT) this._freeImageType, fiMem, FI.FREE_IMAGE_LOAD_FLAGS.DEFAULT); } if (fiBitmap.IsNull) { throw new AxiomException("Error decoding image"); } var imgData = new ImageData(); imgData.depth = 1; // only 2D formats handled by this codec imgData.width = (int)FI.FreeImage.GetWidth(fiBitmap); imgData.height = (int)FI.FreeImage.GetHeight(fiBitmap); imgData.numMipMaps = 0; // no mipmaps in non-DDS // Must derive format first, this may perform conversions var imageType = FI.FreeImage.GetImageType(fiBitmap); var colorType = FI.FreeImage.GetColorType(fiBitmap); var bpp = (int)FI.FreeImage.GetBPP(fiBitmap); switch (imageType) { case FI.FREE_IMAGE_TYPE.FIT_UNKNOWN: case FI.FREE_IMAGE_TYPE.FIT_COMPLEX: case FI.FREE_IMAGE_TYPE.FIT_UINT32: case FI.FREE_IMAGE_TYPE.FIT_INT32: case FI.FREE_IMAGE_TYPE.FIT_DOUBLE: default: throw new AxiomException("Unknown or unsupported image format"); case FI.FREE_IMAGE_TYPE.FIT_BITMAP: // Standard image type // Perform any colour conversions for greyscale if (colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK) { var newBitmap = FI.FreeImage.ConvertToGreyscale(fiBitmap); // free old bitmap and replace FI.FreeImage.Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = (int)FI.FreeImage.GetBPP(fiBitmap); colorType = FI.FreeImage.GetColorType(fiBitmap); } // Perform any colour conversions for RGB else if (bpp < 8 || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_PALETTE || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_CMYK) { var newBitmap = FI.FreeImage.ConvertTo24Bits(fiBitmap); // free old bitmap and replace FI.FreeImage.Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = (int)FI.FreeImage.GetBPP(fiBitmap); colorType = FI.FreeImage.GetColorType(fiBitmap); } // by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A] switch (bpp) { case 8: imgData.format = PixelFormat.L8; break; case 16: // Determine 555 or 565 from green mask // cannot be 16-bit greyscale since that's FIT_UINT16 if (FI.FreeImage.GetGreenMask(fiBitmap) == FI.FreeImage.FI16_565_GREEN_MASK) { imgData.format = PixelFormat.R5G6B5; } else { // FreeImage doesn't support 4444 format so must be 1555 imgData.format = PixelFormat.A1R5G5B5; } break; case 24: // FreeImage differs per platform // PixelFormat.BYTE_BGR[A] for little endian (== PixelFormat.ARGB native) // PixelFormat.BYTE_RGB[A] for big endian (== PixelFormat.RGBA native) if (FI.FreeImage.IsLittleEndian()) { imgData.format = PixelFormat.BYTE_BGR; } else { imgData.format = PixelFormat.BYTE_RGB; } break; case 32: if (FI.FreeImage.IsLittleEndian()) { imgData.format = PixelFormat.BYTE_BGRA; } else { imgData.format = PixelFormat.BYTE_RGBA; } break; } ; break; case FI.FREE_IMAGE_TYPE.FIT_UINT16: case FI.FREE_IMAGE_TYPE.FIT_INT16: // 16-bit greyscale imgData.format = PixelFormat.L16; break; case FI.FREE_IMAGE_TYPE.FIT_FLOAT: // Single-component floating point data imgData.format = PixelFormat.FLOAT32_R; break; case FI.FREE_IMAGE_TYPE.FIT_RGB16: imgData.format = PixelFormat.SHORT_RGB; break; case FI.FREE_IMAGE_TYPE.FIT_RGBA16: imgData.format = PixelFormat.SHORT_RGBA; break; case FI.FREE_IMAGE_TYPE.FIT_RGBF: imgData.format = PixelFormat.FLOAT32_RGB; break; case FI.FREE_IMAGE_TYPE.FIT_RGBAF: imgData.format = PixelFormat.FLOAT32_RGBA; break; } var srcPitch = (int)FI.FreeImage.GetPitch(fiBitmap); // Final data - invert image and trim pitch at the same time var dstPitch = imgData.width * PixelUtil.GetNumElemBytes(imgData.format); imgData.size = dstPitch * imgData.height; // Bind output buffer var outputData = new byte[imgData.size]; using (var srcData = BufferBase.Wrap(FI.FreeImage.GetBits(fiBitmap), imgData.height * srcPitch)) { var pDst = BufferBase.Wrap(outputData); for (var y = 0; y < imgData.height; ++y) { using (var pSrc = srcData + (imgData.height - y - 1) * srcPitch) { Memory.Copy(pSrc, pDst, dstPitch); pDst += dstPitch; } } pDst.Dispose(); } FI.FreeImage.Unload(fiBitmap); FI.FreeImage.CloseMemory(fiMem); return(new Codec.DecodeResult(new MemoryStream(outputData), imgData)); }
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 override Codec.DecodeResult Decode(Stream input) { using (var br = new BinaryReader(input)) { var numFaces = 1; // Assume one face until we know otherwise var imgData = new ImageData(); // Read the PVRTC header var header = PVRTCTexHeader.Read(br); // Get the file type identifier var pvrTag = header.pvrTag; if (this.PVR_MAGIC != pvrTag) { throw new AxiomException("This is not a PVR file!"); } // Get format flags var flags = header.flags; using (var wrap = BufferBase.Wrap(flags, 2)) { _flipEndian(wrap, sizeof(int)); } var formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK; var bitmaskAlpha = header.bitmaskAlpha; using (var wrap = BufferBase.Wrap(bitmaskAlpha, 2)) { _flipEndian(wrap, sizeof(int)); } if (formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2) { if (formatFlags == kPVRTextureFlagTypePVRTC_4) { imgData.format = bitmaskAlpha != 0 ? PixelFormat.PVRTC_RGBA4 : PixelFormat.PVRTC_RGB4; } else if (formatFlags == kPVRTextureFlagTypePVRTC_2) { imgData.format = bitmaskAlpha != 0 ? PixelFormat.PVRTC_RGBA2 : PixelFormat.PVRTC_RGB2; } imgData.depth = 1; imgData.width = header.width; imgData.height = header.height; imgData.numMipMaps = header.numMipmaps; // PVRTC is a compressed format imgData.flags |= ImageFlags.Compressed; } // Calculate total size from number of mipmaps, faces and size imgData.size = Image.CalculateSize(imgData.numMipMaps, numFaces, imgData.width, imgData.height, imgData.depth, imgData.format); // Now deal with the data var dest = br.ReadBytes(imgData.size); return(new DecodeResult(new MemoryStream(dest), imgData)); } }
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); }