internal virtual void BindRenderbuffer(int renderbuffer) { GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderbuffer); GraphicsExtensions.CheckGLError(); }
internal override void DeleteFramebuffer(int id) { GL.Ext.DeleteFramebuffers(1, ref id); GraphicsExtensions.CheckGLError(); }
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 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); }
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 }); }
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(); }); }
internal virtual void GenerateMipmap(int target) { GL.GenerateMipmap((TextureTarget)target); GraphicsExtensions.CheckGLError(); }
internal override void GenerateMipmap(int target) { GL.Ext.GenerateMipmap((GenerateMipmapTarget)target); GraphicsExtensions.CheckGLError(); }
internal virtual void DeleteFramebuffer(int framebuffer) { GL.DeleteFramebuffers(1, ref framebuffer); GraphicsExtensions.CheckGLError(); }
internal virtual void FramebufferRenderbuffer(int attachement, int renderbuffer, int level = 0) { GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, (FramebufferSlot)attachement, RenderbufferTarget.Renderbuffer, renderbuffer); GraphicsExtensions.CheckGLError(); }
internal virtual void BindReadFramebuffer(int readFramebuffer) { GL.BindFramebuffer((FramebufferTarget)AllReadFramebuffer, readFramebuffer); GraphicsExtensions.CheckGLError(); }
internal virtual void BindFramebuffer(int framebuffer) { GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer); GraphicsExtensions.CheckGLError(); }
internal virtual void DeleteRenderbuffer(int renderbuffer) { GL.DeleteRenderbuffers(1, ref renderbuffer); 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(); }
internal virtual void BlitFramebuffer(int iColorAttachment, int width, int height) { this.GLBlitFramebuffer(0, 0, width, height, 0, 0, width, height, ClearBufferMask.ColorBufferBit, TextureMagFilter.Nearest); GraphicsExtensions.CheckGLError(); }
internal override void FramebufferRenderbuffer(int attachement, int renderbuffer, int level = 0) { GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, (FramebufferAttachment)attachement, RenderbufferTarget.Renderbuffer, renderbuffer); GraphicsExtensions.CheckGLError(); }
internal override void BindRenderbuffer(int id) { GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, id); GraphicsExtensions.CheckGLError(); }
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 RenderbufferStorageMultisample(int samples, int internalFormat, int width, int height) { GL.Ext.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, samples, (RenderbufferStorage)internalFormat, width, height); 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 }
internal override void GenFramebuffer(out int id) { GL.Ext.GenFramebuffers(1, out 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; }
internal override void BindFramebuffer(int id) { GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, id); GraphicsExtensions.CheckGLError(); }
/// <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(); }
internal override void BindReadFramebuffer(int readFramebuffer) { GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer); GraphicsExtensions.CheckGLError(); }
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(GraphicsDevice device, bool force = false) { var blendEnabled = !(this.ColorSourceBlend == Blend.One && this.ColorDestinationBlend == Blend.Zero && this.AlphaSourceBlend == Blend.One && this.AlphaDestinationBlend == Blend.Zero); if (force || blendEnabled != device._lastBlendEnable) { if (blendEnabled) { GL.Enable(EnableCap.Blend); } else { GL.Disable(EnableCap.Blend); } GraphicsExtensions.CheckGLError(); device._lastBlendEnable = blendEnabled; } if (force || this.BlendFactor != device._lastBlendState.BlendFactor) { GL.BlendColor( this.BlendFactor.R / 255.0f, this.BlendFactor.G / 255.0f, this.BlendFactor.B / 255.0f, this.BlendFactor.A / 255.0f); GraphicsExtensions.CheckGLError(); device._lastBlendState.BlendFactor = this.BlendFactor; } if (force || this.ColorBlendFunction != device._lastBlendState.ColorBlendFunction || this.AlphaBlendFunction != device._lastBlendState.AlphaBlendFunction) { GL.BlendEquationSeparate( this.ColorBlendFunction.GetBlendEquationMode(), this.AlphaBlendFunction.GetBlendEquationMode()); GraphicsExtensions.CheckGLError(); device._lastBlendState.ColorBlendFunction = this.ColorBlendFunction; device._lastBlendState.AlphaBlendFunction = this.AlphaBlendFunction; } if (force || this.ColorSourceBlend != device._lastBlendState.ColorSourceBlend || this.ColorDestinationBlend != device._lastBlendState.ColorDestinationBlend || this.AlphaSourceBlend != device._lastBlendState.AlphaSourceBlend || this.AlphaDestinationBlend != device._lastBlendState.AlphaDestinationBlend) { GL.BlendFuncSeparate( this.ColorSourceBlend.GetBlendFactorSrc(), this.ColorDestinationBlend.GetBlendFactorDest(), this.AlphaSourceBlend.GetBlendFactorSrc(), this.AlphaDestinationBlend.GetBlendFactorDest()); GraphicsExtensions.CheckGLError(); device._lastBlendState.ColorSourceBlend = this.ColorSourceBlend; device._lastBlendState.ColorDestinationBlend = this.ColorDestinationBlend; device._lastBlendState.AlphaSourceBlend = this.AlphaSourceBlend; device._lastBlendState.AlphaDestinationBlend = this.AlphaDestinationBlend; } if (force || this.ColorWriteChannels != device._lastBlendState.ColorWriteChannels) { GL.ColorMask( (this.ColorWriteChannels & ColorWriteChannels.Red) != 0, (this.ColorWriteChannels & ColorWriteChannels.Green) != 0, (this.ColorWriteChannels & ColorWriteChannels.Blue) != 0, (this.ColorWriteChannels & ColorWriteChannels.Alpha) != 0); GraphicsExtensions.CheckGLError(); device._lastBlendState.ColorWriteChannels = this.ColorWriteChannels; } }