/// <summary> /// Initializes a new instance of the OpenGLRenderTarget2D class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="width">The render target's width in pixels.</param> /// <param name="height">The render target's height in pixels.</param> /// <param name="usage">A <see cref="RenderTargetUsage"/> value specifying whether the /// render target's data is discarded or preserved when it is bound to the graphics device.</param> /// <param name="buffers">The collection of render buffers to attach to the target.</param> public OpenGLRenderTarget2D(UltravioletContext uv, Int32 width, Int32 height, RenderTargetUsage usage, IEnumerable <RenderBuffer2D> buffers = null) : base(uv) { Contract.EnsureRange(width > 0, nameof(width)); Contract.EnsureRange(height > 0, nameof(height)); var framebuffer = 0u; uv.QueueWorkItem(state => { using (OpenGLState.ScopedCreateFramebuffer(out framebuffer)) { if (buffers != null) { foreach (OpenGLRenderBuffer2D buffer in buffers) { AttachRenderBuffer(buffer); } } } }).Wait(); this.width = width; this.height = height; this.framebuffer = framebuffer; this.renderTargetUsage = usage; }
/// <summary> /// Initializes a new instance of the <see cref="OpenGLSamplerObject"/> class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> public OpenGLSamplerObject(UltravioletContext uv) : base(uv) { var sampler = 0u; uv.QueueWorkItem(state => { sampler = gl.GenSampler(); gl.ThrowIfError(); }).Wait(); this.sampler = sampler; }
/// <summary> /// Initializes a new instance of the OpenGLGeometryStream class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> public OpenGLGeometryStream(UltravioletContext uv) : base(uv) { var vao = 0u; if (gl.IsVertexArrayObjectAvailable) { uv.QueueWorkItem(state => { vao = gl.GenVertexArray(); gl.ThrowIfError(); }).Wait(); } this.vao = vao; }
/// <summary> /// Initializes a new instance of the OpenGLIndexBuffer. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> /// <param name="usage">The buffer's usage type.</param> public OpenGLIndexBuffer(UltravioletContext uv, IndexBufferElementType itype, Int32 icount, UInt32 usage) : base(uv, itype, icount) { Contract.EnsureRange(icount >= 0, nameof(icount)); this.usage = usage; this.size = new IntPtr(GetElementSize() * icount); var buffer = 0u; uv.QueueWorkItem(state => { using (OpenGLState.ScopedCreateElementArrayBuffer(out buffer)) { gl.NamedBufferData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, size, null, usage); gl.ThrowIfError(); } }).Wait(); this.buffer = buffer; }
/// <summary> /// Initializes a new instance of the OpenGLVertexBuffer. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="vdecl">The vertex declaration for this buffer.</param> /// <param name="vcount">The number of vertices in the buffer.</param> /// <param name="usage">The buffer's usage type.</param> public OpenGLVertexBuffer(UltravioletContext uv, VertexDeclaration vdecl, Int32 vcount, UInt32 usage) : base(uv, vdecl, vcount) { Contract.Require(vdecl, nameof(vdecl)); this.vdecl = vdecl; this.usage = usage; this.size = new IntPtr(vdecl.VertexStride * vcount); var buffer = 0u; uv.QueueWorkItem(state => { using (OpenGLState.ScopedCreateArrayBuffer(out buffer)) { gl.NamedBufferData(buffer, gl.GL_ARRAY_BUFFER, size, null, usage); gl.ThrowIfError(); } }).Wait(); this.buffer = buffer; }
/// <summary> /// Creates the underlying native OpenGL texture with the specified format and data. /// </summary> private void CreateNativeTexture(UltravioletContext uv, UInt32 internalformat, Int32 width, Int32 height, Int32 depth, UInt32 format, UInt32 type, void *pixels, Boolean immutable) { if (uv.IsRunningInServiceMode) { throw new NotSupportedException(UltravioletStrings.NotSupportedInServiceMode); } this.width = width; this.height = height; this.depth = depth; this.internalformat = internalformat; this.format = format; this.type = type; this.immutable = immutable; this.srgbEncoded = internalformat == gl.GL_SRGB || internalformat == gl.GL_SRGB_ALPHA || internalformat == gl.GL_SRGB8 || internalformat == gl.GL_SRGB8_ALPHA8; this.texture = uv.QueueWorkItem(state => { uint glname; using (OpenGLState.ScopedCreateTexture3D(out glname)) { if (gl.IsTextureMaxLevelSupported) { gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAX_LEVEL, 0); gl.ThrowIfError(); } gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, (int)gl.GL_LINEAR); gl.ThrowIfError(); gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, (int)gl.GL_LINEAR); gl.ThrowIfError(); gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_R, (int)gl.GL_CLAMP_TO_EDGE); gl.ThrowIfError(); gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_S, (int)gl.GL_CLAMP_TO_EDGE); gl.ThrowIfError(); gl.TextureParameteri(glname, gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_T, (int)gl.GL_CLAMP_TO_EDGE); gl.ThrowIfError(); if (immutable) { if (gl.IsTextureStorageAvailable) { gl.TextureStorage3D(glname, gl.GL_TEXTURE_3D, 1, internalformat, width, height, depth); gl.ThrowIfError(); if (pixels != null) { gl.TextureSubImage3D(glname, gl.GL_TEXTURE_3D, 0, 0, 0, 0, width, height, depth, format, type, pixels); gl.ThrowIfError(); } } else { gl.TextureImage3D(glname, gl.GL_TEXTURE_3D, 0, (int)internalformat, width, height, depth, 0, format, type, pixels); gl.ThrowIfError(); } } } if (!immutable) { using (OpenGLState.ScopedBindTexture3D(glname, true)) { gl.TexImage3D(gl.GL_TEXTURE_3D, 0, (int)internalformat, width, height, depth, 0, format, type, pixels); gl.ThrowIfError(); } } return(glname); }).Result; }
/// <summary> /// Initializes a new instance of the OpenGLShaderProgram class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="vertexShader">The program's vertex shader.</param> /// <param name="fragmentShader">The program's fragment shader.</param> /// <param name="programOwnsShaders">A value indicating whether the program owns the shader objects.</param> public OpenGLShaderProgram(UltravioletContext uv, OpenGLVertexShader vertexShader, OpenGLFragmentShader fragmentShader, Boolean programOwnsShaders) : base(uv) { Contract.Require(vertexShader, nameof(vertexShader)); Contract.Require(fragmentShader, nameof(fragmentShader)); Ultraviolet.ValidateResource(vertexShader); Ultraviolet.ValidateResource(fragmentShader); this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.programOwnsShaders = programOwnsShaders; var concatenatedSourceMetadata = new ShaderSourceMetadata(); concatenatedSourceMetadata.Concat(vertexShader.ShaderSourceMetadata); concatenatedSourceMetadata.Concat(fragmentShader.ShaderSourceMetadata); var program = 0u; uv.QueueWorkItem(state => { program = gl.CreateProgram(); gl.ThrowIfError(); gl.AttachShader(program, vertexShader.OpenGLName); gl.ThrowIfError(); gl.AttachShader(program, fragmentShader.OpenGLName); gl.ThrowIfError(); gl.LinkProgram(program); gl.ThrowIfError(); var log = gl.GetProgramInfoLog(program); gl.ThrowIfError(); var status = gl.GetProgrami(program, gl.GL_LINK_STATUS); gl.ThrowIfError(); var attributeCount = gl.GetProgrami(program, gl.GL_ACTIVE_ATTRIBUTES); gl.ThrowIfError(); unsafe { var namebuf = Marshal.AllocHGlobal(256); try { for (int i = 0; i < attributeCount; i++) { var attrNameLen = 0; var attrName = default(String); var attrSize = 0; var attrType = 0u; gl.GetActiveAttrib(program, (uint)i, 256, &attrNameLen, &attrSize, &attrType, (sbyte *)namebuf); gl.ThrowIfError(); attrName = Marshal.PtrToStringAnsi(namebuf); var location = gl.GetAttribLocation(program, attrName); gl.ThrowIfError(); attributeLocations[attrName] = location; attributeTypes[attrName] = attrType; } } finally { Marshal.FreeHGlobal(namebuf); } } if (status == 0) { throw new InvalidOperationException(log); } }).Wait(); this.program = program; this.uniforms = CreateUniformCollection(concatenatedSourceMetadata); }