/// <summary> /// Sets the texture's data. /// </summary> private void SetDataInternal <T>(Int32 level, Int32 left, Int32 top, Int32 right, Int32 bottom, Int32 front, Int32 back, T[] data, Int32 startIndex, Int32 elementCount) where T : struct { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var width = right - left; var height = bottom - top; var depth = back - front; var pixelSizeInBytes = (format == gl.GL_RGB || format == gl.GL_BGR) ? 3 : 4; if (pixelSizeInBytes * width * height * depth != elementSizeInBytes * elementCount) { throw new ArgumentException(UltravioletStrings.BufferIsWrongSize); } Ultraviolet.QueueWorkItem(state => { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { using (OpenGLState.ScopedBindTexture3D(OpenGLName)) { var pData = dataHandle.AddrOfPinnedObject() + (startIndex * elementSizeInBytes); gl.TextureSubImage3D(OpenGLName, gl.GL_TEXTURE_3D, level, left, top, front, right - left, bottom - top, back - front, format, type, (void *)pData); gl.ThrowIfError(); } } finally { dataHandle.Free(); } }).Wait(); }
/// <summary> /// Processes a resize operation for this texture. /// </summary> private void ProcessResize() { using (OpenGLState.ScopedBindTexture3D(texture, true)) { gl.TexImage3D(gl.GL_TEXTURE_3D, 0, (int)internalformat, width, height, depth, 0, format, type, null); } }
/// <summary> /// Uploads texture data to the graphics device. /// </summary> private void Upload(Int32 level, Int32 left, Int32 top, Int32 right, Int32 bottom, Int32 front, Int32 back, IntPtr data, Int32 offsetInBytes, Int32 sizeInBytes) { using (OpenGLState.ScopedBindTexture3D(OpenGLName)) { var pData = data + offsetInBytes; gl.TextureSubImage3D(OpenGLName, gl.GL_TEXTURE_3D, level, left, top, front, right - left, bottom - top, back - front, format, type, (void *)pData); gl.ThrowIfError(); } }
/// <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; }