internal void SetVertexAttributeArray(bool[] attrs) { for (int x = 0; x < attrs.Length; x++) { if (attrs[x] && !_enabledVertexAttributes.Contains(x)) { _enabledVertexAttributes.Add(x); GL.EnableVertexAttribArray(x); GraphicsExtensions.CheckGLError(); } else if (!attrs[x] && _enabledVertexAttributes.Contains(x)) { _enabledVertexAttributes.Remove(x); GL.DisableVertexAttribArray(x); GraphicsExtensions.CheckGLError(); } } }
internal void Apply(Shader shader, IntPtr offset) { VertexDeclarationAttributeInfo attrInfo; int shaderHash = shader.GetHashCode(); if (!shaderAttributeInfo.TryGetValue(shaderHash, out attrInfo)) { // Get the vertex attribute info and cache it attrInfo = new VertexDeclarationAttributeInfo(GraphicsDevice.MaxVertexAttributes); foreach (var ve in InternalVertexElements) { var attributeLocation = shader.GetAttribLocation(ve.VertexElementUsage, ve.UsageIndex); // XNA appears to ignore usages it can't find a match for, so we will do the same if (attributeLocation >= 0) { attrInfo.Elements.Add(new VertexDeclarationAttributeInfo.Element() { Offset = ve.Offset, AttributeLocation = attributeLocation, NumberOfElements = ve.VertexElementFormat.OpenGLNumberOfElements(), VertexAttribPointerType = ve.VertexElementFormat.OpenGLVertexAttribPointerType(), Normalized = ve.OpenGLVertexAttribNormalized(), }); attrInfo.EnabledAttributes[attributeLocation] = true; } } shaderAttributeInfo.Add(shaderHash, attrInfo); } // Apply the vertex attribute info foreach (var element in attrInfo.Elements) { GL.VertexAttribPointer(element.AttributeLocation, element.NumberOfElements, element.VertexAttribPointerType, element.Normalized, this.VertexStride, (IntPtr)(offset.ToInt64() + element.Offset)); GraphicsExtensions.CheckGLError(); } GraphicsDevice.SetVertexAttributeArray(attrInfo.EnabledAttributes); }
private void PlatformSetData <T>(CubeMapFace face, int level, IntPtr dataPtr, int xOffset, int yOffset, int width, int height) { Threading.BlockOnUIThread(() => { GL.BindTexture(TextureTarget.TextureCubeMap, this.glTexture); GraphicsExtensions.CheckGLError(); TextureTarget target = GetGLCubeFace(face); if (glFormat == (PixelFormat)GLPixelFormat.CompressedTextureFormats) { throw new NotImplementedException(); } else { GL.TexSubImage2D(target, level, xOffset, yOffset, width, height, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } }); }
private void SetBufferData <T>(int bufferSize, int elementSizeInBytes, int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { GenerateIfRequired(); var sizeInBytes = elementSizeInBytes * elementCount; GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); GraphicsExtensions.CheckGLError(); if (options == SetDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes); int dataSize = Marshal.SizeOf(typeof(T)); if (dataSize == vertexStride) { GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr); GraphicsExtensions.CheckGLError(); } else { for (int i = 0; i < elementCount; i++) { GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes + i * vertexStride, (IntPtr)dataSize, dataPtr); GraphicsExtensions.CheckGLError(); dataPtr = (IntPtr)(dataPtr.ToInt64() + dataSize); } } dataHandle.Free(); }
public void PlatformPresent() { #if DESKTOPGL || ANGLE Context.SwapBuffers(); #endif GraphicsExtensions.CheckGLError(); // Dispose of any GL resources that were disposed in another thread lock ( disposeActionsLock ) { if (disposeActions.Count > 0) { foreach (var action in disposeActions) { action(); } disposeActions.Clear(); } } }
private void PlatformSetViewport(ref Viewport value) { if (IsRenderTargetBound) { GL.Viewport(value.X, value.Y, value.Width, value.Height); } else { GL.Viewport(value.X, PresentationParameters.BackBufferHeight - value.Y - value.Height, value.Width, value.Height); } GraphicsExtensions.LogGLError("GraphicsDevice.Viewport_set() GL.Viewport"); #if GLES GL.DepthRange(value.MinDepth, value.MaxDepth); #else GL.DepthRange(value.MinDepth, value.MaxDepth); #endif GraphicsExtensions.LogGLError("GraphicsDevice.Viewport_set() GL.DepthRange"); // In OpenGL we have to re-apply the special "posFixup" // vertex shader uniform if the viewport changes. _vertexShaderDirty = true; }
private void PlatformDrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, int startIndex, int primitiveCount) { ApplyState(true); var shortIndices = _indexBuffer.IndexElementSize == IndexElementSize.SixteenBits; var indexElementType = shortIndices ? DrawElementsType.UnsignedShort : DrawElementsType.UnsignedInt; var indexElementSize = shortIndices ? 2 : 4; var indexOffsetInBytes = (IntPtr)(startIndex * indexElementSize); var indexElementCount = GetElementCountArray(primitiveType, primitiveCount); var target = PrimitiveTypeGL(primitiveType); var vertexDeclaration = _vertexBuffers.Get(0).VertexBuffer.VertexDeclaration; var vertexOffset = (IntPtr)(vertexDeclaration.VertexStride * baseVertex); vertexDeclaration.Apply(_vertexShader, vertexOffset); GL.DrawElements(target, indexElementCount, indexElementType, indexOffsetInBytes); GraphicsExtensions.CheckGLError(); }
private void PlatformSetData <T>(int level, int left, int top, int right, int bottom, int front, int back, T[] data, int startIndex, int elementCount, int width, int height, int depth) { #if GLES throw new NotSupportedException("OpenGL ES 2.0 doesn't support 3D textures."); #else Threading.BlockOnUIThread(() => { var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); GL.BindTexture(glTarget, glTexture); GraphicsExtensions.CheckGLError(); GL.TexSubImage3D(glTarget, level, left, top, front, width, height, depth, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); dataHandle.Free(); }); #endif }
internal int GetShaderHandle() { // If the shader has already been created then return it. if (_shaderHandle != -1) { return(_shaderHandle); } // _shaderHandle = GL.CreateShader(Stage == ShaderStage.Vertex ? ShaderType.VertexShader : ShaderType.FragmentShader); GraphicsExtensions.CheckGLError(); GL.ShaderSource(_shaderHandle, _glslCode); GraphicsExtensions.CheckGLError(); GL.CompileShader(_shaderHandle); GraphicsExtensions.CheckGLError(); int compiled = 0; GL.GetShader(_shaderHandle, ShaderParameter.CompileStatus, out compiled); GraphicsExtensions.CheckGLError(); if (compiled != (int)Bool.True) { var log = GL.GetShaderInfoLog(_shaderHandle); Console.WriteLine(log); if (GL.IsShader(_shaderHandle)) { GL.DeleteShader(_shaderHandle); GraphicsExtensions.CheckGLError(); } _shaderHandle = -1; throw new InvalidOperationException("Shader Compilation Failed"); } return(_shaderHandle); }
private void PlatformSetup() { #if DESKTOPGL || ANGLE var windowInfo = new WindowInfo(SdlGameWindow.Instance.Handle); if (Context == null || Context.IsDisposed) { Context = GL.CreateContext(windowInfo); } Context.MakeCurrent(windowInfo); Context.SwapInterval = PresentationParameters.PresentationInterval.GetSwapInterval(); /*if (Threading.BackgroundContext == null) * { * Threading.BackgroundContext = GL.CreateContext(windowInfo); * Threading.WindowInfo = windowInfo; * Threading.BackgroundContext.MakeCurrent(null); * }*/ Context.MakeCurrent(windowInfo); /*GraphicsMode mode = GraphicsMode.Default; * var wnd = OpenTK.Platform.Utilities.CreateSdl2WindowInfo(Game.Instance.Window.Handle); * #if GLES * // Create an OpenGL ES 2.0 context * var flags = GraphicsContextFlags.Embedded; * int major = 2; * int minor = 0; #else * // Create an OpenGL compatibility context * var flags = GraphicsContextFlags.Default; * int major = 1; * int minor = 0; #endif * * if (Context == null || Context.IsDisposed) * { * var color = PresentationParameters.BackBufferFormat.GetColorFormat(); * var depth = * PresentationParameters.DepthStencilFormat == DepthFormat.None ? 0 : * PresentationParameters.DepthStencilFormat == DepthFormat.Depth16 ? 16 : * 24; * var stencil = * PresentationParameters.DepthStencilFormat == DepthFormat.Depth24Stencil8 ? 8 : * 0; * * var samples = 0; * if (Game.Instance.graphicsDeviceManager.PreferMultiSampling) * { * // Use a default of 4x samples if PreferMultiSampling is enabled * // without explicitly setting the desired MultiSampleCount. * if (PresentationParameters.MultiSampleCount == 0) * { * PresentationParameters.MultiSampleCount = 4; * } * * samples = PresentationParameters.MultiSampleCount; * } * * mode = new GraphicsMode(color, depth, stencil, samples); * try * { * Context = new GraphicsContext(mode, wnd, major, minor, flags); * } * catch (Exception e) * { * Game.Instance.Log("Failed to create OpenGL context, retrying. Error: " + * e.ToString()); * major = 1; * minor = 0; * flags = GraphicsContextFlags.Default; * Context = new GraphicsContext(mode, wnd, major, minor, flags); * } * } * Context.MakeCurrent(wnd); * (Context as IGraphicsContextInternal).LoadAll(); * Context.SwapInterval = PresentationParameters.PresentationInterval.GetSwapInterval(); * * // Provide the graphics context for background loading * // Note: this context should use the same GraphicsMode, * // major, minor version and flags parameters as the main * // context. Otherwise, context sharing will very likely fail. * if (Threading.BackgroundContext == null) * { * Threading.BackgroundContext = new GraphicsContext(mode, wnd, major, minor, flags); * Threading.WindowInfo = wnd; * Threading.BackgroundContext.MakeCurrent(null); * } * Context.MakeCurrent(wnd);*/ #endif MaxTextureSlots = 16; GL.GetInteger(GetPName.MaxTextureImageUnits, out MaxTextureSlots); GraphicsExtensions.CheckGLError(); GL.GetInteger(GetPName.MaxVertexAttribs, out MaxVertexAttributes); GraphicsExtensions.CheckGLError(); GL.GetInteger(GetPName.MaxTextureSize, out _maxTextureSize); GraphicsExtensions.CheckGLError(); SpriteBatch.NeedsHalfPixelOffset = true; // try getting the context version // GL_MAJOR_VERSION and GL_MINOR_VERSION are GL 3.0+ only, so we need to rely on the GL_VERSION string // for non GLES this string always starts with the version number in the "major.minor" format, but can be followed by // multiple vendor specific characters // For GLES this string is formatted as: OpenGL<space>ES<space><version number><space><vendor-specific information> #if GLES try { string version = GL.GetString(StringName.Version); string[] versionSplit = version.Split(' '); if (versionSplit.Length > 2 && versionSplit[0].Equals("OpenGL") && versionSplit[1].Equals("ES")) { glMajorVersion = Convert.ToInt32(versionSplit[2].Substring(0, 1)); glMinorVersion = Convert.ToInt32(versionSplit[2].Substring(2, 1)); } else { glMajorVersion = 1; glMinorVersion = 1; } } catch (FormatException) { //if it fails we default to 1.1 context glMajorVersion = 1; glMinorVersion = 1; } #else try { string version = GL.GetString(StringName.Version); glMajorVersion = Convert.ToInt32(version.Substring(0, 1)); glMinorVersion = Convert.ToInt32(version.Substring(2, 1)); } catch (FormatException) { // if it fails, we assume to be on a 1.1 context glMajorVersion = 1; glMinorVersion = 1; } #endif #if !GLES // Initialize draw buffer attachment array int maxDrawBuffers; GL.GetInteger(GetPName.MaxDrawBuffers, out maxDrawBuffers); GraphicsExtensions.CheckGLError(); _drawBuffers = new DrawBuffersEnum[maxDrawBuffers]; for (int i = 0; i < maxDrawBuffers; i++) { _drawBuffers[i] = (DrawBuffersEnum)(FramebufferAttachment.ColorAttachment0Ext + i); } #endif _extensions = GetGLExtensions(); }
internal void PlatformApplyState(bool applyShaders) { if (_scissorRectangleDirty) { var scissorRect = _scissorRectangle; if (!IsRenderTargetBound) { scissorRect.Y = _viewport.Height - scissorRect.Y - scissorRect.Height; } GL.Scissor(scissorRect.X, scissorRect.Y, scissorRect.Width, scissorRect.Height); GraphicsExtensions.CheckGLError(); _scissorRectangleDirty = false; } // If we're not applying shaders then early out now. if (!applyShaders) { return; } if (_indexBufferDirty) { if (_indexBuffer != null) { GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.ibo); GraphicsExtensions.CheckGLError(); } _indexBufferDirty = false; } if (_vertexBuffersDirty) { if (_vertexBuffers.Count > 0) { GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffers.Get(0).VertexBuffer.vbo); GraphicsExtensions.CheckGLError(); } _vertexBuffersDirty = false; } if (_vertexShader == null) { throw new InvalidOperationException("A vertex shader must be set!"); } if (_pixelShader == null) { throw new InvalidOperationException("A pixel shader must be set!"); } if (_vertexShaderDirty || _pixelShaderDirty) { ActivateShaderProgram(); if (_vertexShaderDirty) { unchecked { _graphicsMetrics._vertexShaderCount++; } } if (_pixelShaderDirty) { unchecked { _graphicsMetrics._pixelShaderCount++; } } _vertexShaderDirty = _pixelShaderDirty = false; } _vertexConstantBuffers.SetConstantBuffers(this, _shaderProgram); _pixelConstantBuffers.SetConstantBuffers(this, _shaderProgram); Textures.SetTextures(this); SamplerStates.PlatformSetSamplers(this); }
internal override void FramebufferRenderbuffer(int attachement, int renderbuffer, int level = 0) { GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, (FramebufferAttachment)attachement, RenderbufferTarget.Renderbuffer, renderbuffer); GraphicsExtensions.CheckGLError(); }
internal void Initialize(GraphicsDevice device) { SupportsNonPowerOfTwo = GetNonPowerOfTwo(device); #if OPENGL SupportsTextureFilterAnisotropic = device._extensions.Contains("GL_EXT_texture_filter_anisotropic"); #else SupportsTextureFilterAnisotropic = true; #endif #if GLES SupportsDepth24 = device._extensions.Contains("GL_OES_depth24"); SupportsPackedDepthStencil = device._extensions.Contains("GL_OES_packed_depth_stencil"); SupportsDepthNonLinear = device._extensions.Contains("GL_NV_depth_nonlinear"); SupportsTextureMaxLevel = device._extensions.Contains("GL_APPLE_texture_max_level"); #else SupportsDepth24 = true; SupportsPackedDepthStencil = true; SupportsDepthNonLinear = false; SupportsTextureMaxLevel = true; #endif // Texture compression #if DIRECTX SupportsDxt1 = true; SupportsS3tc = true; #elif OPENGL SupportsS3tc = device._extensions.Contains("GL_EXT_texture_compression_s3tc") || device._extensions.Contains("GL_OES_texture_compression_S3TC") || device._extensions.Contains("GL_EXT_texture_compression_dxt3") || device._extensions.Contains("GL_EXT_texture_compression_dxt5"); SupportsDxt1 = SupportsS3tc || device._extensions.Contains("GL_EXT_texture_compression_dxt1"); SupportsPvrtc = device._extensions.Contains("GL_IMG_texture_compression_pvrtc"); SupportsEtc1 = device._extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture"); SupportsAtitc = device._extensions.Contains("GL_ATI_texture_compression_atitc") || device._extensions.Contains("GL_AMD_compressed_ATC_texture"); #endif // OpenGL framebuffer objects #if OPENGL #if GLES SupportsFramebufferObjectARB = true; // always supported on GLES 2.0+ SupportsFramebufferObjectEXT = false; #else // if we're on GL 3.0+, frame buffer extensions are guaranteed to be present, but extensions may be missing // it is then safe to assume that GL_ARB_framebuffer_object is present so that the standard function are loaded SupportsFramebufferObjectARB = device.glMajorVersion >= 3 || device._extensions.Contains("GL_ARB_framebuffer_object"); SupportsFramebufferObjectEXT = device._extensions.Contains("GL_EXT_framebuffer_object"); #endif #endif // Anisotropic filtering #if OPENGL int anisotropy = 0; if (SupportsTextureFilterAnisotropic) { #if __IOS__ GL.GetInteger((GetPName)All.MaxTextureMaxAnisotropyExt, out anisotropy); #else GL.GetInteger((GetPName)GetParamName.MaxTextureMaxAnisotropyExt, out anisotropy); #endif GraphicsExtensions.CheckGLError(); } MaxTextureAnisotropy = anisotropy; #endif // sRGB #if DIRECTX SupportsSRgb = true; #elif OPENGL #if GLES SupportsSRgb = device._extensions.Contains("GL_EXT_sRGB"); #else SupportsSRgb = device._extensions.Contains("GL_EXT_texture_sRGB") && device._extensions.Contains("GL_EXT_framebuffer_sRGB"); #endif #endif #if DIRECTX SupportsTextureArrays = device.GraphicsProfile == GraphicsProfile.HiDef; #elif OPENGL // TODO: Implement OpenGL support for texture arrays // once we can author shaders that use texture arrays. SupportsTextureArrays = false; #endif #if DIRECTX SupportsDepthClamp = device.GraphicsProfile == GraphicsProfile.HiDef; #elif OPENGL SupportsDepthClamp = device._extensions.Contains("GL_ARB_depth_clamp"); #endif #if DIRECTX SupportsVertexTextures = device.GraphicsProfile == GraphicsProfile.HiDef; #elif OPENGL SupportsVertexTextures = false; // For now, until we implement vertex textures in OpenGL. #endif }
internal void Activate(GraphicsDevice device, TextureTarget target, bool useMipmaps = false) { if (GraphicsDevice == null) { // We're now bound to a device... no one should // be changing the state of this object now! GraphicsDevice = device; } Debug.Assert(GraphicsDevice == device, "The state was created for a different device!"); switch (Filter) { case TextureFilter.Point: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.NearestMipmapNearest : TextureMinFilter.Nearest)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GraphicsExtensions.CheckGLError(); break; case TextureFilter.Linear: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.LinearMipmapLinear : TextureMinFilter.Linear)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GraphicsExtensions.CheckGLError(); break; case TextureFilter.Anisotropic: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, MathUtil.Clamp(this.MaxAnisotropy, 1.0f, GraphicsDevice.GraphicsCapabilities.MaxTextureAnisotropy)); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.LinearMipmapLinear : TextureMinFilter.Linear)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GraphicsExtensions.CheckGLError(); break; case TextureFilter.PointMipLinear: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.NearestMipmapLinear : TextureMinFilter.Nearest)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GraphicsExtensions.CheckGLError(); break; case TextureFilter.LinearMipPoint: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.LinearMipmapNearest : TextureMinFilter.Linear)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GraphicsExtensions.CheckGLError(); break; case TextureFilter.MinLinearMagPointMipLinear: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.LinearMipmapLinear : TextureMinFilter.Linear)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GraphicsExtensions.CheckGLError(); break; case TextureFilter.MinLinearMagPointMipPoint: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.LinearMipmapNearest : TextureMinFilter.Linear)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GraphicsExtensions.CheckGLError(); break; case TextureFilter.MinPointMagLinearMipLinear: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.NearestMipmapLinear : TextureMinFilter.Nearest)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GraphicsExtensions.CheckGLError(); break; case TextureFilter.MinPointMagLinearMipPoint: if (GraphicsDevice.GraphicsCapabilities.SupportsTextureFilterAnisotropic) { GL.TexParameter(target, TextureParameterNameTextureMaxAnisotropy, 1.0f); GraphicsExtensions.CheckGLError(); } GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)(useMipmaps ? TextureMinFilter.NearestMipmapNearest : TextureMinFilter.Nearest)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GraphicsExtensions.CheckGLError(); break; default: throw new NotSupportedException(); } // Set up texture addressing. GL.TexParameter(target, TextureParameterName.TextureWrapS, (int)GetWrapMode(AddressU)); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureWrapT, (int)GetWrapMode(AddressV)); GraphicsExtensions.CheckGLError(); #if !GLES // Border color is not supported by glTexParameter in OpenGL ES 2.0 _openGLBorderColor[0] = BorderColor.R / 255.0f; _openGLBorderColor[1] = BorderColor.G / 255.0f; _openGLBorderColor[2] = BorderColor.B / 255.0f; _openGLBorderColor[3] = BorderColor.A / 255.0f; GL.TexParameter(target, TextureParameterName.TextureBorderColor, _openGLBorderColor); GraphicsExtensions.CheckGLError(); // LOD bias is not supported by glTexParameter in OpenGL ES 2.0 GL.TexParameter(target, TextureParameterName.TextureLodBias, MipMapLevelOfDetailBias); GraphicsExtensions.CheckGLError(); // Comparison samplers are not supported in OpenGL ES 2.0 (without an extension, anyway) if (ComparisonFunction != CompareFunction.Never) { GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)TextureCompareMode.CompareRefToTexture); GraphicsExtensions.CheckGLError(); GL.TexParameter(target, TextureParameterName.TextureCompareFunc, (int)ComparisonFunction.GetDepthFunction()); GraphicsExtensions.CheckGLError(); } else { GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)TextureCompareMode.None); GraphicsExtensions.CheckGLError(); } #endif if (GraphicsDevice.GraphicsCapabilities.SupportsTextureMaxLevel) { if (this.MaxMipLevel > 0) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterNameTextureMaxLevel, this.MaxMipLevel); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterNameTextureMaxLevel, 1000); } } }
internal override void DeleteFramebuffer(int id) { GL.Ext.DeleteFramebuffers(1, ref id); GraphicsExtensions.CheckGLError(); }
public void PlatformClear(ClearOptions options, Vector4 color, float depth, int stencil) { // TODO: We need to figure out how to detect if we have a // depth stencil buffer or not, and clear options relating // to them if not attached. // Unlike with XNA and DirectX... GL.Clear() obeys several // different render states: // // - The color write flags. // - The scissor rectangle. // - The depth/stencil state. // // So overwrite these states with what is needed to perform // the clear correctly and restore it afterwards. // var prevScissorRect = ScissorRectangle; var prevDepthStencilState = DepthStencilState; var prevBlendState = BlendState; ScissorRectangle = _viewport.Bounds; // DepthStencilState.Default has the Stencil Test disabled; // make sure stencil test is enabled before we clear since // some drivers won't clear with stencil test disabled DepthStencilState = this.clearDepthStencilState; BlendState = BlendState.Opaque; ApplyState(false); ClearBufferMask bufferMask = 0; if ((options & ClearOptions.Target) == ClearOptions.Target) { if (color != _lastClearColor) { GL.ClearColor(color.X, color.Y, color.Z, color.W); GraphicsExtensions.CheckGLError(); _lastClearColor = color; } bufferMask = bufferMask | ClearBufferMask.ColorBufferBit; } if ((options & ClearOptions.Stencil) == ClearOptions.Stencil) { if (stencil != _lastClearStencil) { GL.ClearStencil(stencil); GraphicsExtensions.CheckGLError(); _lastClearStencil = stencil; } bufferMask = bufferMask | ClearBufferMask.StencilBufferBit; } if ((options & ClearOptions.DepthBuffer) == ClearOptions.DepthBuffer) { if (depth != _lastClearDepth) { #if GLES GL.ClearDepth(depth); #else GL.ClearDepth(depth); #endif GraphicsExtensions.CheckGLError(); _lastClearDepth = depth; } bufferMask = bufferMask | ClearBufferMask.DepthBufferBit; } GL.Clear(bufferMask); GraphicsExtensions.CheckGLError(); // Restore the previous render state. ScissorRectangle = prevScissorRect; DepthStencilState = prevDepthStencilState; BlendState = prevBlendState; }
private void PlatformConstruct(int width, int height, bool mipmap, SurfaceFormat format, SurfaceType type, bool shared) { this.glTarget = TextureTarget.Texture2D; Threading.BlockOnUIThread(() => { // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); format.GetGLFormat(GraphicsDevice, out glInternalFormat, out glFormat, out glType); if (glFormat == (PixelFormat)GLPixelFormat.CompressedTextureFormats) { var imageSize = 0; switch (format) { case SurfaceFormat.RgbPvrtc2Bpp: case SurfaceFormat.RgbaPvrtc2Bpp: imageSize = (Math.Max(this.width, 16) * Math.Max(this.height, 8) * 2 + 7) / 8; break; case SurfaceFormat.RgbPvrtc4Bpp: case SurfaceFormat.RgbaPvrtc4Bpp: imageSize = (Math.Max(this.width, 8) * Math.Max(this.height, 8) * 4 + 7) / 8; break; case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: case SurfaceFormat.Dxt1SRgb: case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt3SRgb: case SurfaceFormat.Dxt5: case SurfaceFormat.Dxt5SRgb: case SurfaceFormat.RgbEtc1: case SurfaceFormat.RgbaAtcExplicitAlpha: case SurfaceFormat.RgbaAtcInterpolatedAlpha: imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * GraphicsExtensions.GetSize(format); break; default: throw new NotSupportedException(); } GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, this.width, this.height, 0, imageSize, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, this.width, this.height, 0, glFormat, glType, IntPtr.Zero); GraphicsExtensions.CheckGLError(); } // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); }); }
private void PlatformGetData <T>(int level, int arraySlice, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct { #if GLES // TODO: check for data size and for non renderable formats (formats that can't be attached to FBO) var framebufferId = 0; #if (IOS || ANDROID) GL.GenFramebuffers(1, out framebufferId); #else GL.GenFramebuffers(1, ref framebufferId); #endif GraphicsExtensions.CheckGLError(); GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebufferId); GraphicsExtensions.CheckGLError(); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, TextureTarget.Texture2D, this.glTexture, 0); GraphicsExtensions.CheckGLError(); var x = 0; var y = 0; var width = this.width; var height = this.height; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; width = this.Width; height = this.Height; } GL.ReadPixels(x, y, width, height, this.glFormat, this.glType, data); GraphicsExtensions.CheckGLError(); GL.DeleteFramebuffers(1, ref framebufferId); GraphicsExtensions.CheckGLError(); #else GL.BindTexture(TextureTarget.Texture2D, this.glTexture); if (glFormat == (PixelFormat)GLPixelFormat.CompressedTextureFormats) { throw new NotImplementedException(); } else { if (rect.HasValue) { var temp = new T[this.width * this.height]; GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, temp); int z = 0, w = 0; for (int y = rect.Value.Y; y < rect.Value.Y + rect.Value.Height; ++y) { for (int x = rect.Value.X; x < rect.Value.X + rect.Value.Width; ++x) { data[z * rect.Value.Width + w] = temp[(y * width) + x]; ++w; } ++z; w = 0; } } else { GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, data); } } #endif }
private void PlatformSetData <T>(int level, int arraySlice, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct { Threading.BlockOnUIThread(() => { var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); // Use try..finally to make sure dataHandle is freed in case of an error try { var startBytes = startIndex * elementSizeInByte; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); int x, y, w, h; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; w = rect.Value.Width; h = rect.Value.Height; } else { x = 0; y = 0; w = Math.Max(width >> level, 1); h = Math.Max(height >> level, 1); // For DXT textures the width and height of each level is a multiple of 4. // OpenGL only: The last two mip levels require the width and height to be // passed as 2x2 and 1x1, but there needs to be enough data passed to occupy // a 4x4 block. // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html if (_format == SurfaceFormat.Dxt1 || _format == SurfaceFormat.Dxt1a || _format == SurfaceFormat.Dxt3 || _format == SurfaceFormat.Dxt5 || _format == SurfaceFormat.RgbaAtcExplicitAlpha || _format == SurfaceFormat.RgbaAtcInterpolatedAlpha || _format == SurfaceFormat.RgbPvrtc2Bpp || _format == SurfaceFormat.RgbPvrtc4Bpp || _format == SurfaceFormat.RgbaPvrtc2Bpp || _format == SurfaceFormat.RgbaPvrtc4Bpp || _format == SurfaceFormat.RgbEtc1 ) { if (w > 4) { w = (w + 3) & ~3; } if (h > 4) { h = (h + 3) & ~3; } } } // Store the current bound texture. var prevTexture = GraphicsExtensions.GetBoundTexture2D(); GenerateGLTextureIfRequired(); GL.BindTexture(TextureTarget.Texture2D, this.glTexture); GraphicsExtensions.CheckGLError(); if (glFormat == (PixelFormat)GLPixelFormat.CompressedTextureFormats) { if (rect.HasValue) { GL.CompressedTexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, glFormat, elementCount - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, elementCount - startBytes, dataPtr); GraphicsExtensions.CheckGLError(); } } else { // Set pixel alignment to match texel size in bytes GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.GetSize(this.Format)); if (rect.HasValue) { GL.TexSubImage2D(TextureTarget.Texture2D, level, x, y, w, h, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } else { GL.TexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, glFormat, glType, dataPtr); GraphicsExtensions.CheckGLError(); } // Return to default pixel alignment GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); } #if !ANDROID GL.Finish(); GraphicsExtensions.CheckGLError(); #endif // Restore the bound texture. GL.BindTexture(TextureTarget.Texture2D, prevTexture); GraphicsExtensions.CheckGLError(); } finally { dataHandle.Free(); } #if !ANDROID // Required to make sure that any texture uploads on a thread are completed // before the main thread tries to use the texture. GL.Finish(); #endif }); }
internal void PlatformApplyState(GraphicsDevice device, bool force = false) { // When rendering offscreen the faces change order. var offscreen = device.IsRenderTargetBound; if (force) { // Turn off dithering to make sure data returned by Texture.GetData is accurate GL.Disable(EnableCap.Dither); } if (CullMode == CullMode.None) { GL.Disable(EnableCap.CullFace); GraphicsExtensions.CheckGLError(); } else { GL.Enable(EnableCap.CullFace); GraphicsExtensions.CheckGLError(); GL.CullFace(CullFaceMode.Back); GraphicsExtensions.CheckGLError(); if (CullMode == CullMode.CullClockwiseFace) { if (offscreen) { GL.FrontFace(FrontFaceDirection.Cw); } else { GL.FrontFace(FrontFaceDirection.Ccw); } GraphicsExtensions.CheckGLError(); } else { if (offscreen) { GL.FrontFace(FrontFaceDirection.Ccw); } else { GL.FrontFace(FrontFaceDirection.Cw); } GraphicsExtensions.CheckGLError(); } } #if MONOMAC || WINDOWS || DESKTOPGL if (FillMode == FillMode.Solid) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } #else if (FillMode != FillMode.Solid) { throw new NotImplementedException(); } #endif if (force || this.ScissorTestEnable != device._lastRasterizerState.ScissorTestEnable) { if (ScissorTestEnable) { GL.Enable(EnableCap.ScissorTest); } else { GL.Disable(EnableCap.ScissorTest); } GraphicsExtensions.CheckGLError(); device._lastRasterizerState.ScissorTestEnable = this.ScissorTestEnable; } if (force || this.DepthBias != device._lastRasterizerState.DepthBias || this.SlopeScaleDepthBias != device._lastRasterizerState.SlopeScaleDepthBias) { if (this.DepthBias != 0 || this.SlopeScaleDepthBias != 0) { GL.Enable(EnableCap.PolygonOffsetFill); GL.PolygonOffset(this.SlopeScaleDepthBias, this.DepthBias); } else { GL.Disable(EnableCap.PolygonOffsetFill); } GraphicsExtensions.CheckGLError(); device._lastRasterizerState.DepthBias = this.DepthBias; device._lastRasterizerState.SlopeScaleDepthBias = this.SlopeScaleDepthBias; } if (device.GraphicsCapabilities.SupportsDepthClamp && (force || this.DepthClipEnable != device._lastRasterizerState.DepthClipEnable)) { if (!DepthClipEnable) { GL.Enable((EnableCap)0x864F); // should be EnableCap.DepthClamp, but not available in OpenTK.Graphics.ES20.EnableCap } else { GL.Disable((EnableCap)0x864F); } GraphicsExtensions.CheckGLError(); device._lastRasterizerState.DepthClipEnable = this.DepthClipEnable; } // TODO: Implement MultiSampleAntiAlias }
internal override void GenerateMipmap(int target) { GL.Ext.GenerateMipmap((GenerateMipmapTarget)target); GraphicsExtensions.CheckGLError(); }
internal override void BindFramebuffer(int id) { GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, id); GraphicsExtensions.CheckGLError(); }
internal void PlatformApplyState(GraphicsDevice device, bool force = false) { if (force || this.DepthBufferEnable != device._lastDepthStencilState.DepthBufferEnable) { if (!DepthBufferEnable) { GL.Disable(EnableCap.DepthTest); GraphicsExtensions.CheckGLError(); } else { // enable Depth Buffer GL.Enable(EnableCap.DepthTest); GraphicsExtensions.CheckGLError(); } device._lastDepthStencilState.DepthBufferEnable = this.DepthBufferEnable; } if (force || this.DepthBufferFunction != device._lastDepthStencilState.DepthBufferFunction) { GL.DepthFunc(DepthBufferFunction.GetDepthFunction()); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.DepthBufferFunction = this.DepthBufferFunction; } if (force || this.DepthBufferWriteEnable != device._lastDepthStencilState.DepthBufferWriteEnable) { GL.DepthMask(DepthBufferWriteEnable); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.DepthBufferWriteEnable = this.DepthBufferWriteEnable; } if (force || this.StencilEnable != device._lastDepthStencilState.StencilEnable) { if (!StencilEnable) { GL.Disable(EnableCap.StencilTest); GraphicsExtensions.CheckGLError(); } else { // enable Stencil GL.Enable(EnableCap.StencilTest); GraphicsExtensions.CheckGLError(); } device._lastDepthStencilState.StencilEnable = this.StencilEnable; } // set function if (this.TwoSidedStencilMode) { #if GLES var cullFaceModeFront = CullFaceMode.Front; var cullFaceModeBack = CullFaceMode.Back; var stencilFaceFront = CullFaceMode.Front; var stencilFaceBack = CullFaceMode.Back; #elif MONOMAC var cullFaceModeFront = (Version20)CullFaceMode.Front; var cullFaceModeBack = (Version20)CullFaceMode.Back; var stencilFaceFront = StencilFace.Front; var stencilFaceBack = StencilFace.Back; #else var cullFaceModeFront = StencilFace.Front; var cullFaceModeBack = StencilFace.Back; var stencilFaceFront = StencilFace.Front; var stencilFaceBack = StencilFace.Back; #endif if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.StencilFunction != device._lastDepthStencilState.StencilFunction || this.ReferenceStencil != device._lastDepthStencilState.ReferenceStencil || this.StencilMask != device._lastDepthStencilState.StencilMask) { GL.StencilFuncSeparate(cullFaceModeFront, GetStencilFunc(this.StencilFunction), this.ReferenceStencil, this.StencilMask); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.StencilFunction = this.StencilFunction; device._lastDepthStencilState.ReferenceStencil = this.ReferenceStencil; device._lastDepthStencilState.StencilMask = this.StencilMask; } if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.CounterClockwiseStencilFunction != device._lastDepthStencilState.CounterClockwiseStencilFunction || this.ReferenceStencil != device._lastDepthStencilState.ReferenceStencil || this.StencilMask != device._lastDepthStencilState.StencilMask) { GL.StencilFuncSeparate(cullFaceModeBack, GetStencilFunc(this.CounterClockwiseStencilFunction), this.ReferenceStencil, this.StencilMask); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.CounterClockwiseStencilFunction = this.CounterClockwiseStencilFunction; device._lastDepthStencilState.ReferenceStencil = this.ReferenceStencil; device._lastDepthStencilState.StencilMask = this.StencilMask; } if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.StencilFail != device._lastDepthStencilState.StencilFail || this.StencilDepthBufferFail != device._lastDepthStencilState.StencilDepthBufferFail || this.StencilPass != device._lastDepthStencilState.StencilPass) { GL.StencilOpSeparate(stencilFaceFront, GetStencilOp(this.StencilFail), GetStencilOp(this.StencilDepthBufferFail), GetStencilOp(this.StencilPass)); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.StencilFail = this.StencilFail; device._lastDepthStencilState.StencilDepthBufferFail = this.StencilDepthBufferFail; device._lastDepthStencilState.StencilPass = this.StencilPass; } if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.CounterClockwiseStencilFail != device._lastDepthStencilState.CounterClockwiseStencilFail || this.CounterClockwiseStencilDepthBufferFail != device._lastDepthStencilState.CounterClockwiseStencilDepthBufferFail || this.CounterClockwiseStencilPass != device._lastDepthStencilState.CounterClockwiseStencilPass) { GL.StencilOpSeparate(stencilFaceBack, GetStencilOp(this.CounterClockwiseStencilFail), GetStencilOp(this.CounterClockwiseStencilDepthBufferFail), GetStencilOp(this.CounterClockwiseStencilPass)); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.CounterClockwiseStencilFail = this.CounterClockwiseStencilFail; device._lastDepthStencilState.CounterClockwiseStencilDepthBufferFail = this.CounterClockwiseStencilDepthBufferFail; device._lastDepthStencilState.CounterClockwiseStencilPass = this.CounterClockwiseStencilPass; } } else { if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.StencilFunction != device._lastDepthStencilState.StencilFunction || this.ReferenceStencil != device._lastDepthStencilState.ReferenceStencil || this.StencilMask != device._lastDepthStencilState.StencilMask) { GL.StencilFunc(GetStencilFunc(this.StencilFunction), ReferenceStencil, StencilMask); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.StencilFunction = this.StencilFunction; device._lastDepthStencilState.ReferenceStencil = this.ReferenceStencil; device._lastDepthStencilState.StencilMask = this.StencilMask; } if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode || this.StencilFail != device._lastDepthStencilState.StencilFail || this.StencilDepthBufferFail != device._lastDepthStencilState.StencilDepthBufferFail || this.StencilPass != device._lastDepthStencilState.StencilPass) { GL.StencilOp(GetStencilOp(StencilFail), GetStencilOp(StencilDepthBufferFail), GetStencilOp(StencilPass)); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.StencilFail = this.StencilFail; device._lastDepthStencilState.StencilDepthBufferFail = this.StencilDepthBufferFail; device._lastDepthStencilState.StencilPass = this.StencilPass; } } device._lastDepthStencilState.TwoSidedStencilMode = this.TwoSidedStencilMode; if (force || this.StencilWriteMask != device._lastDepthStencilState.StencilWriteMask) { GL.StencilMask(this.StencilWriteMask); GraphicsExtensions.CheckGLError(); device._lastDepthStencilState.StencilWriteMask = this.StencilWriteMask; } }
private void PlatformResolveRenderTargets() { if (this._currentRenderTargetCount == 0) { return; } var renderTargetBinding = this._currentRenderTargetBindings[0]; var renderTarget = renderTargetBinding.RenderTarget as IRenderTarget; if (renderTarget.MultiSampleCount > 0 && this.framebufferHelper.SupportsBlitFramebuffer) { var glResolveFramebuffer = 0; if (!this.glResolveFramebuffers.TryGetValue(this._currentRenderTargetBindings, out glResolveFramebuffer)) { this.framebufferHelper.GenFramebuffer(out glResolveFramebuffer); this.framebufferHelper.BindFramebuffer(glResolveFramebuffer); for (var i = 0; i < this._currentRenderTargetCount; ++i) { this.framebufferHelper.FramebufferTexture2D((int)(FramebufferAttachment.ColorAttachment0 + i), (int)renderTarget.GetFramebufferTarget(renderTargetBinding), renderTarget.GLTexture); } this.glResolveFramebuffers.Add((RenderTargetBinding[])this._currentRenderTargetBindings.Clone(), glResolveFramebuffer); } else { this.framebufferHelper.BindFramebuffer(glResolveFramebuffer); } // The only fragment operations which affect the resolve are the pixel ownership test, the scissor test, and dithering. if (this._lastRasterizerState.ScissorTestEnable) { GL.Disable(EnableCap.ScissorTest); GraphicsExtensions.CheckGLError(); } var glFramebuffer = this.glFramebuffers[this._currentRenderTargetBindings]; this.framebufferHelper.BindReadFramebuffer(glFramebuffer); for (var i = 0; i < this._currentRenderTargetCount; ++i) { renderTargetBinding = this._currentRenderTargetBindings[i]; renderTarget = renderTargetBinding.RenderTarget as IRenderTarget; this.framebufferHelper.BlitFramebuffer(i, renderTarget.Width, renderTarget.Height); } if (renderTarget.RenderTargetUsage == RenderTargetUsage.DiscardContents && this.framebufferHelper.SupportsInvalidateFramebuffer) { this.framebufferHelper.InvalidateReadFramebuffer(); } if (this._lastRasterizerState.ScissorTestEnable) { GL.Enable(EnableCap.ScissorTest); GraphicsExtensions.CheckGLError(); } } for (var i = 0; i < this._currentRenderTargetCount; ++i) { renderTargetBinding = this._currentRenderTargetBindings[i]; renderTarget = renderTargetBinding.RenderTarget as IRenderTarget; if (renderTarget.LevelCount > 1) { GL.BindTexture((TextureTarget)renderTarget.GLTarget, renderTarget.GLTexture); GraphicsExtensions.CheckGLError(); this.framebufferHelper.GenerateMipmap((int)renderTarget.GLTarget); } } }
internal override void GenFramebuffer(out int id) { GL.Ext.GenFramebuffers(1, out id); GraphicsExtensions.CheckGLError(); }
internal override void BindReadFramebuffer(int readFramebuffer) { GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer); GraphicsExtensions.CheckGLError(); }
/// <summary> /// Runs the given action on the UI thread and blocks the current thread while the action is running. /// If the current thread is the UI thread, the action will run immediately. /// </summary> /// <param name="action">The action to be run on the UI thread</param> internal static void BlockOnUIThread(Action action) { if (action == null) { throw new ArgumentNullException("action"); } #if (DIRECTX && !WINDOWS_PHONE) || PSM action(); #else // If we are already on the UI thread, just call the action and be done with it if (IsOnUIThread()) { #if WINDOWS_PHONE try { action(); } catch (UnauthorizedAccessException) { // Need to be on a different thread BlockOnContainerThread(Deployment.Current.Dispatcher, action); } #else action(); #endif return; } #if IOS lock (BackgroundContext) { // Make the context current on this thread if it is not already if (!Object.ReferenceEquals(EAGLContext.CurrentContext, BackgroundContext)) { EAGLContext.SetCurrentContext(BackgroundContext); } // Execute the action action(); // Must flush the GL calls so the GPU asset is ready for the main context to use it GL.Flush(); GraphicsExtensions.CheckGLError(); } #elif WINDOWS_PHONE BlockOnContainerThread(Deployment.Current.Dispatcher, action); #else ManualResetEventSlim resetEvent = new ManualResetEventSlim(false); #if MONOMAC #if PLATFORM_MACOS_LEGACY MonoMac.AppKit.NSApplication.SharedApplication.BeginInvokeOnMainThread(() => #else AppKit.NSApplication.SharedApplication.BeginInvokeOnMainThread(() => #endif #else Add(() => #endif { #if ANDROID //if (!Game.Instance.Window.GraphicsContext.IsCurrent) ((AndroidGameWindow)Game.Instance.Window).GameView.MakeCurrent(); #endif action(); resetEvent.Set(); }); resetEvent.Wait(); #endif #endif }
/// <summary> /// Activates the Current Vertex/Pixel shader pair into a program. /// </summary> private unsafe void ActivateShaderProgram() { // Lookup the shader program. var shaderProgram = _programCache.GetProgram(VertexShader, PixelShader); if (shaderProgram.Program == -1) { return; } // Set the new program if it has changed. if (_shaderProgram != shaderProgram) { GL.UseProgram(shaderProgram.Program); GraphicsExtensions.CheckGLError(); _shaderProgram = shaderProgram; } var posFixupLoc = shaderProgram.GetUniformLocation("posFixup"); if (posFixupLoc == -1) { return; } // Apply vertex shader fix: // The following two lines are appended to the end of vertex shaders // to account for rendering differences between OpenGL and DirectX: // // gl_Position.y = gl_Position.y * posFixup.y; // gl_Position.xy += posFixup.zw * gl_Position.ww; // // (the following paraphrased from wine, wined3d/state.c and wined3d/glsl_shader.c) // // - We need to flip along the y-axis in case of offscreen rendering. // - D3D coordinates refer to pixel centers while GL coordinates refer // to pixel corners. // - D3D has a top-left filling convention. We need to maintain this // even after the y-flip mentioned above. // In order to handle the last two points, we translate by // (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to // translating slightly less than half a pixel. We want the difference to // be large enough that it doesn't get lost due to rounding inside the // driver, but small enough to prevent it from interfering with any // anti-aliasing. // // OpenGL coordinates specify the center of the pixel while d3d coords specify // the corner. The offsets are stored in z and w in posFixup. posFixup.y contains // 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x // contains 1.0 to allow a mad. _posFixup[0] = 1.0f; _posFixup[1] = 1.0f; _posFixup[2] = (63.0f / 64.0f) / Viewport.Width; _posFixup[3] = -(63.0f / 64.0f) / Viewport.Height; //If we have a render target bound (rendering offscreen) if (IsRenderTargetBound) { //flip vertically _posFixup[1] *= -1.0f; _posFixup[3] *= -1.0f; } fixed(float *floatPtr = _posFixup) { GL.Uniform4(posFixupLoc, 1, floatPtr); } GraphicsExtensions.CheckGLError(); }
private void PlatformConstruct() { GL.GenQueries(1, out glQueryId); GraphicsExtensions.CheckGLError(); }
internal override void FramebufferTexture2D(int attachement, int target, int texture, int level = 0, int samples = 0) { GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, (FramebufferAttachment)attachement, (TextureTarget)target, texture, level); GraphicsExtensions.CheckGLError(); }