Example #1
0
        /// <summary>
        /// Define the fake GPU buffer (when GL_ARB_vertex_array_object is not supported) using the current client buffer.
        /// </summary>
        protected virtual void UploadClientBuffer()
        {
            if (_MemoryBufferAutoDispose == false)
            {
                // Note: client buffer is expected to be allocated and modificable; even while the GPU is rendering
                // using the simulated GPU buffer. We need to copy: in this way it is implemented the double buffer
                // mechanism of the GL_ARB_vertex_buffer_object extension

                // Allocate a new GPU buffer
                _GpuBuffer = new AlignedMemoryBuffer(ClientBufferSize, MinimumBufferAlignment);
                // Copy from client buffer
                Memory.MemoryCopy(_GpuBuffer.AlignedBuffer, ClientBufferAddress, ClientBufferSize);
            }
            else
            {
                // Note: since client buffer need to be disposed (ending set to null), we do not copy
                // client buffer to GPU buffer; instead, switch references and do not dispose the client buffer

                // Allocate GPU buffer
                _GpuBuffer = _ClientBuffer;
                // Do not need disposition (not really sure, but apart ClientBufferAddress, no reference of _ClientBuffer
                // should be out of here
                _ClientBuffer = null;
            }
        }
Example #2
0
 /// <summary>
 /// Allocate a new client buffer for this BufferObject.
 /// </summary>
 /// <param name="size">
 /// A <see cref="UInt32"/> that determine the size of the buffer object client buffer, in bytes.
 /// </param>
 protected virtual void AllocateClientBuffer(uint size)
 {
     // Discard previous buffer
     ReleaseClientBuffer();
     // Allocate memory, if required
     _ClientBuffer = new AlignedMemoryBuffer(size, MinimumBufferAlignment);
 }
        /// <summary>
        /// Copy data from another AlignedMemoryBuffer.
        /// </summary>
        /// <param name="otherMemoryBuffer">
        /// A <see cref="AlignedMemoryBuffer"/> which has allocated the data to be copied.
        /// </param>
        /// <param name="otherOffset">
        /// A <see cref="UInt64"/> which specify an additional offset (in bytes) to apply to <paramref name="otherMemoryBuffer"/>.
        /// </param>
        /// <param name="thisOffset">
        /// A <see cref="UInt64"/> which specify an additional offset (in bytes) to apply to this AlignedMemoryBuffer.
        /// </param>
        /// <param name="bytesCopied">
        /// A <see cref="UInt64"/> which specify the number of bytes to be copied.
        /// </param>
        public void CopyBuffer(AlignedMemoryBuffer otherMemoryBuffer, ulong otherOffset, ulong thisOffset, ulong bytesCopied)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException("AlignedMemoryBuffer");
            }
            if (otherMemoryBuffer == null)
            {
                throw new ArgumentNullException("otherMemoryBuffer");
            }
            if (otherMemoryBuffer._UnmanagedBuffer == IntPtr.Zero)
            {
                throw new ArgumentException("disposed", "otherMemoryBuffer");
            }
            if (thisOffset + bytesCopied >= otherMemoryBuffer.Size - otherOffset)
            {
                throw new InvalidOperationException("copying out of bounds");
            }

            if (bytesCopied > 0)
            {
                IntPtr src = new IntPtr(otherMemoryBuffer.AlignedBuffer.ToInt64() + (long)otherOffset);
                IntPtr dst = new IntPtr(AlignedBuffer.ToInt64() + (long)thisOffset);

                Memory.MemoryCopy(dst, src, bytesCopied);
            }
        }
Example #4
0
 /// <summary>
 /// Performs application-defined tasks associated with freeing, releasing, or resetting managed/unmanaged resources.
 /// </summary>
 /// <param name="disposing">
 /// </param>
 protected override void Dispose(bool disposing)
 {
     if (disposing)
     {
         if (_PixelBuffers != null)
         {
             // Release the buffer buffer
             _PixelBuffers.Dispose();
             _PixelBuffers = null;
         }
     }
 }
Example #5
0
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting managed/unmanaged resources.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown in the case <see cref="GraphicsResource.RefCount"/> is greater than zero. This means that the method is trying to dispose
        /// an object that is actually referenced by something else.
        /// </exception>
        protected override void Dispose(bool disposing)
        {
            // Base implementation
            base.Dispose(disposing);

            if (disposing == true)
            {
                // Simulated GPU buffer is disposed at disposition
                if (_GpuBuffer != null)
                {
                    _GpuBuffer.Dispose();
                    _GpuBuffer = null;
                    // Reset GPU buffer size
                    _GpuBufferSize = 0;
                }

                // Release client buffer
                ReleaseClientBuffer();
            }
        }
Example #6
0
        /// <summary>
        /// Actually create this BufferObject resources.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for allocating resources.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="ctx"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Exception thrown if <paramref name="ctx"/> is not current on the calling thread.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this BufferObject has not client memory allocated and the hint is different from
        /// <see cref="BufferObjectHint.StaticCpuDraw"/> or <see cref="BufferObjectHint.DynamicCpuDraw"/>.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this BufferObject is currently mapped.
        /// </exception>
        protected override void CreateObject(GraphicsContext ctx)
        {
            CheckCurrentContext(ctx);

            if ((ClientBufferAddress == IntPtr.Zero) && ((Hint != BufferObjectHint.StaticCpuDraw) && (Hint != BufferObjectHint.DynamicCpuDraw)))
            {
                throw new InvalidOperationException("no client buffer");
            }

            // Determine the client buffer size
            uint clientBufferSize = _ClientBufferSize;

            if (ClientBufferAddress != IntPtr.Zero)
            {
                clientBufferSize = ClientBufferSize;
            }

            Debug.Assert(clientBufferSize > 0);

            // Buffer must be bound
            Bind(ctx);

            if (ctx.Caps.GlExtensions.VertexBufferObject_ARB)
            {
                if (IsMapped)
                {
                    throw new InvalidOperationException("mapped");
                }

                // Define buffer object (type, size and hints)
                Gl.BufferData((int)BufferType, clientBufferSize, null, (int)Hint);
                // Store GPU buffer size
                _GpuBufferSize = clientBufferSize;

                // Define buffer object contents
                if (ClientBufferAddress != IntPtr.Zero)
                {
                    // Provide buffer contents
                    Gl.BufferSubData(BufferType, IntPtr.Zero, _GpuBufferSize, ClientBufferAddress);
                    // Release memory, if it is not required anymore
                    if (_MemoryBufferAutoDispose)
                    {
                        ReleaseClientBuffer();
                    }
                }
            }
            else
            {
                // Discard previous GPU buffer, if any
                if (_GpuBuffer != null)
                {
                    _GpuBuffer.Dispose();
                }

                if (ClientBufferAddress == IntPtr.Zero)
                {
                    // Note: GPU buffer size specified by _ClientBufferSize
                    Debug.Assert(_ClientBufferSize > 0);
                    // Allocate simulated GPU buffer
                    _GpuBuffer = new AlignedMemoryBuffer(_ClientBufferSize, MinimumBufferAlignment);
                }
                else
                {
                    // Let a virtual implementation decide how pass information from the client buffer and the "GPU" buffer
                    UploadClientBuffer();
                }

                // Store GPU buffer size
                _GpuBufferSize = _GpuBuffer.Size;
            }

            // Reset requested client buffer size
            _ClientBufferSize = 0;
        }
Example #7
0
        /// <summary>
        /// Allocate pixel data for this Image.
        /// </summary>
        /// <param name="format">
        /// A <see cref="PixelLayout"/> indicating the image pixel format.
        /// </param>
        /// <param name="w">
        /// A <see cref="Int32"/> indicating the image width, in pixels.
        /// </param>
        /// <param name="h">
        /// A <see cref="Int32"/> indicating the image height, in pixels.
        /// </param>
        public void Create(PixelLayout format, uint w, uint h)
        {
            PixelLayoutInfo formatInfo = Pixel.GetPixelFormat(format);

            switch (format)
            {
            // Single plane formats
            case PixelLayout.GRAY8:
            case PixelLayout.GRAY16:
            case PixelLayout.GRAYF:
            case PixelLayout.GRAYHF:
            case PixelLayout.GRAYAF:
            case PixelLayout.RGB8:
            case PixelLayout.RGB15:
            case PixelLayout.RGB16:
            case PixelLayout.RGB24:
            case PixelLayout.RGB48:
            case PixelLayout.RGBF:
            case PixelLayout.RGBHF:
            case PixelLayout.RGBD:
            case PixelLayout.SRGB24:
            case PixelLayout.SBGR24:
            case PixelLayout.RGB30A2:
            case PixelLayout.RGBA32:
            case PixelLayout.RGBA64:
            case PixelLayout.RGBAF:
            case PixelLayout.RGBAHF:
            case PixelLayout.BGR8:
            case PixelLayout.BGR15:
            case PixelLayout.BGR16:
            case PixelLayout.BGR24:
            case PixelLayout.BGR48:
            case PixelLayout.BGRF:
            case PixelLayout.BGRHF:
            case PixelLayout.BGR30A2:
            case PixelLayout.BGRA32:
            case PixelLayout.BGRA64:
            case PixelLayout.BGRAF:
            case PixelLayout.BGRAHF:
            case PixelLayout.CMY24:
            case PixelLayout.CMYK32:
            case PixelLayout.CMYK64:
            case PixelLayout.CMYKA40:
            case PixelLayout.Depth16:
            case PixelLayout.Depth24:
            case PixelLayout.Depth32:
            case PixelLayout.DepthF:
            case PixelLayout.Depth24Stencil8:
            case PixelLayout.Depth32FStencil8:
            case PixelLayout.Integer1:
            case PixelLayout.Integer2:
            case PixelLayout.Integer3:
            case PixelLayout.Integer4:
            case PixelLayout.UInteger1:
            case PixelLayout.UInteger2:
            case PixelLayout.UInteger3:
            case PixelLayout.UInteger4:
                _PixelBuffers = new AlignedMemoryBuffer(w * h * formatInfo.PixelBytes, 16);
                // Define planes
                _PixelPlanes = new IntPtr[] { _PixelBuffers.AlignedBuffer };
                break;

            case PixelLayout.YUYV:
            case PixelLayout.YYUV:
            case PixelLayout.YVYU:
            case PixelLayout.UYVY:
            case PixelLayout.VYUY:
                if (((w % 2) != 0) || ((h % 2) != 0))
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                // Define planes
                _PixelBuffers = new AlignedMemoryBuffer(w * h * formatInfo.PixelBytes, 16);
                _PixelPlanes  = new IntPtr[] { _PixelBuffers.AlignedBuffer };
                break;

            case PixelLayout.YVU410:
            case PixelLayout.YUV410:
                if (((w % 16) != 0) || ((h % 16) != 0))
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                _PixelBuffers = new AlignedMemoryBuffer(w * h + (w * h / 16) * 2, 16);
                // Define planes
                _PixelPlanes    = new IntPtr[3];
                _PixelPlanes[0] = _PixelBuffers.AlignedBuffer;
                _PixelPlanes[1] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h);
                _PixelPlanes[2] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h + (w * h / 16));
                break;

            case PixelLayout.YVU420:
            case PixelLayout.YUV420:
                if (((w % 4) != 0) || ((h % 4) != 0))
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                _PixelBuffers = new AlignedMemoryBuffer(w * h + (w * h / 4), 16);
                // Define planes
                _PixelPlanes    = new IntPtr[3];
                _PixelPlanes[0] = _PixelBuffers.AlignedBuffer;
                _PixelPlanes[1] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h);
                _PixelPlanes[2] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h + (w * h / 4));
                break;

            case PixelLayout.YUV422P:
                if ((w % 2) != 0)
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                _PixelBuffers = new AlignedMemoryBuffer(w * h + (w * h / 2), 16);
                // Define planes
                _PixelPlanes    = new IntPtr[3];
                _PixelPlanes[0] = _PixelBuffers.AlignedBuffer;
                _PixelPlanes[1] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h);
                _PixelPlanes[2] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h + (w * h / 2));
                break;

            case PixelLayout.YUV411P:
                if ((w % 4) != 0)
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                _PixelBuffers = new AlignedMemoryBuffer(w * h + (w * h / 4), 16);
                // Define planes
                _PixelPlanes    = new IntPtr[3];
                _PixelPlanes[0] = _PixelBuffers.AlignedBuffer;
                _PixelPlanes[1] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h);
                _PixelPlanes[2] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h + (w * h / 4));
                break;

            case PixelLayout.Y41P:
                if ((w % 8) != 0)
                {
                    throw new InvalidOperationException(String.Format("invalid image extents for pixel format {0}", format));
                }
                _PixelBuffers = new AlignedMemoryBuffer(w * h * 12 / 8, 16);
                // Define planes
                _PixelPlanes    = new IntPtr[3];
                _PixelPlanes[0] = _PixelBuffers.AlignedBuffer;
                _PixelPlanes[1] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h);
                _PixelPlanes[2] = new IntPtr(_PixelBuffers.AlignedBuffer.ToInt64() + w * h + (w * h / 4));
                break;

            default:
                throw new NotSupportedException(String.Format("pixel format {0} is not supported", format));
            }
            // Set image information
            _ImageInfo.PixelType = formatInfo.DataFormat;
            _ImageInfo.Width     = w;
            _ImageInfo.Height    = h;
            // Store pixel format
            _PixelFormat = formatInfo;

            Debug.Assert(_PixelPlanes != null);
            Debug.Assert(_PixelPlanes.Length != 0);
            Debug.Assert(Array.TrueForAll(_PixelPlanes, delegate(IntPtr pixelPlane) { return(pixelPlane != IntPtr.Zero); }));
        }
		/// <summary>
		/// Copy data from another AlignedMemoryBuffer. 
		/// </summary>
		/// <param name="otherMemoryBuffer">
		/// A <see cref="AlignedMemoryBuffer"/> which has allocated the data to be copied.
		/// </param>
		/// <param name="otherOffset">
		/// A <see cref="UInt64"/> which specify an additional offset (in bytes) to apply to <paramref name="otherMemoryBuffer"/>.
		/// </param>
		/// <param name="thisOffset">
		/// A <see cref="UInt64"/> which specify an additional offset (in bytes) to apply to this AlignedMemoryBuffer.
		/// </param>
		/// <param name="bytesCopied">
		/// A <see cref="UInt64"/> which specify the number of bytes to be copied.
		/// </param>
		public void CopyBuffer(AlignedMemoryBuffer otherMemoryBuffer, ulong otherOffset, ulong thisOffset, ulong bytesCopied)
		{
			if (IsDisposed)
				throw new ObjectDisposedException("AlignedMemoryBuffer");
			if (otherMemoryBuffer == null)
				throw new ArgumentNullException("otherMemoryBuffer");
			if (otherMemoryBuffer._UnmanagedBuffer == IntPtr.Zero)
				throw new ArgumentException("disposed", "otherMemoryBuffer");
			if (thisOffset + bytesCopied >= otherMemoryBuffer.Size - otherOffset)
				throw new InvalidOperationException("copying out of bounds");

			if (bytesCopied > 0) {
				IntPtr src = new IntPtr(otherMemoryBuffer.AlignedBuffer.ToInt64() + (long)otherOffset);
				IntPtr dst = new IntPtr(AlignedBuffer.ToInt64() + (long)thisOffset);

				Memory.MemoryCopy(dst, src, bytesCopied);
			}
		}