/// <inheritdoc/> public override void Attach(RenderBuffer2D buffer) { Contract.Require(buffer, nameof(buffer)); Contract.Ensure <ArgumentException>( buffer.Width == width && buffer.Height == height, OpenGLStrings.RenderBufferIsWrongSize); Contract.EnsureNotDisposed(this, Disposed); Ultraviolet.ValidateResource(buffer); var sdlBuffer = (OpenGLRenderBuffer2D)buffer; Ultraviolet.QueueWorkItemAndWait(() => { using (OpenGLState.ScopedBindFramebuffer(framebuffer)) { AttachRenderBuffer(sdlBuffer); framebufferStatus = gl.CheckNamedFramebufferStatus(framebuffer, gl.GL_FRAMEBUFFER); gl.ThrowIfError(); } }); sdlBuffer.MarkAttached(); buffers.Add(sdlBuffer); }
/// <summary> /// Gets the render target's data. /// </summary> /// <param name="data">An array to populate with the render target's data.</param> /// <param name="region">The region of the render target from which to retrieve data.</param> private unsafe void GetDataInternal(Color[] data, Rectangle region) { using (OpenGLState.ScopedBindFramebuffer(framebuffer, true)) { fixed(Color *pData = data) { if (!gl.IsGLES2) { gl.ReadBuffer(gl.GL_COLOR_ATTACHMENT0); gl.ThrowIfError(); } gl.ReadPixels(region.X, region.Y, region.Width, region.Height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, pData); gl.ThrowIfError(); } } // OpenGL texture data is stored upside down and in the wrong color format, // so we need to convert that to what our caller expects. var rowsToProcess = (Height % 2 == 0) ? Height / 2 : 1 + Height / 2; for (int y = 0; y < rowsToProcess; y++) { var ySrc = (y); var yDst = (Height - 1) - y; for (int x = 0; x < Width; x++) { var ixSrc = (ySrc * Width) + x; var ixDst = (yDst * Width) + x; var colorSrc = new Color(data[ixSrc].PackedValue); var colorDst = new Color(data[ixDst].PackedValue); data[ixDst] = colorSrc; data[ixSrc] = colorDst; } } }