public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer) { //Update the shadow buffer if (useShadowBuffer) { var destData = shadowBuffer.Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal); src = destData; shadowBuffer.Unlock(); } if (offset == 0 && length == sizeInBytes) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), src.Pin(), GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { if (discardWholeBuffer) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(offset), new IntPtr(length), src.Pin()); GLES2Config.GlCheckError(this); } }
///<summary> /// This function acts very similar to <see cref="GLES2FBORenderTexture.AttachDepthBuffer">The difference between D3D & OGL is that D3D setups the DepthBuffer before rendering, /// while OGL setups the DepthBuffer per FBO. So the DepthBuffer (RenderBuffer) needs to /// be attached for OGL. ///</summary> ///<param name="depthBuffer"> </param> public void AttachDepthBuffer(DepthBuffer depthBuffer) { var glDepthBuffer = depthBuffer as GLES2DepthBuffer; GL.BindFramebuffer(GLenum.Framebuffer, this._multiSampleFB > 0 ? this._multiSampleFB : this._fb); GLES2Config.GlCheckError(this); if (glDepthBuffer != null) { GLES2RenderBuffer depthBuf = glDepthBuffer.DepthBuffer; GLES2RenderBuffer stencilBuf = glDepthBuffer.StencilBuffer; //Attach depth buffer, if it has one. if (depthBuf != null) { depthBuf.BindToFramebuffer(GLenum.DepthAttachment, 0); } //Attach stencil buffer, if it has one. if (stencilBuf != null) { stencilBuf.BindToFramebuffer(GLenum.StencilAttachment, 0); } } else { GL.FramebufferRenderbuffer(GLenum.Framebuffer, GLenum.DepthAttachment, GLenum.Renderbuffer, 0); GLES2Config.GlCheckError(this); GL.FramebufferRenderbuffer(GLenum.Framebuffer, GLenum.StencilAttachment, GLenum.Renderbuffer, 0); GLES2Config.GlCheckError(this); } }
protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); //Update whole buffer if possible, otherwise normal if (lockStart == 0 && lockSize == sizeInBytes) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), srcData.Pin(), GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { //Ogre FIXME: GPU frequently stalls here - DJR GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcData.Pin()); GLES2Config.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
public GLES2HardwareIndexBuffer(HardwareBufferManagerBase manager, IndexType type, int numIndices, BufferUsage usage, bool useShadowBuffer) : base(manager, type, numIndices, usage, false, useShadowBuffer) { if (type == IndexType.Size32) { throw new AxiomException("32 bit hardware buffers are not allowed in OpenGL ES."); } if (!useShadowBuffer) { throw new AxiomException("Only support with shadowBuffer"); } OpenGL.GenBuffers(1, ref this._bufferId); GLES2Config.GlCheckError(this); if (this._bufferId == 0) { throw new AxiomException("Cannot create GL index buffer"); } OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); }
public GLES2FrameBufferObject(GLES2FBOManager manager, int fsaa) { this._manager = manager; this._numSamples = fsaa; GL.GenFramebuffers(1, ref this._fb); GLES2Config.GlCheckError(this); this._numSamples = 0; this._multiSampleFB = 0; /*Port notes * Ogre has a #if GL_APPLE_framebuffer_multisample * conditional here for checking if multisampling is supported * however GLenum doesn't contain members for what it's checking for * so this will skipped by default */ //Will we need a second FBO to do multisampling? if (this._numSamples > 0) { GL.GenFramebuffers(1, ref this._multiSampleFB); GLES2Config.GlCheckError(this); } //Initialize state this._depth.buffer = null; this._stencil.buffer = null; for (int x = 0; x < Axiom.Configuration.Config.MaxMultipleRenderTargets; x++) { this._color[x].buffer = null; } }
/// <summary> /// Bind FrameBufferObject /// </summary> public void Bind() { //Bind it to FBO var fb = this._multiSampleFB > 0 ? this._multiSampleFB : this._fb; GL.BindFramebuffer(GLenum.Framebuffer, fb); GLES2Config.GlCheckError(this); }
protected override void dispose(bool disposeManagedResources) { GL.DeleteBuffers(1, ref this._bufferID); GLES2Config.GlCheckError(this); (Root.Instance.RenderSystem as GLES2RenderSystem).DeleteGLBuffer(GLenum.ArrayBuffer, this._bufferID); base.dispose(disposeManagedResources); }
public void Bind() { #if !AXIOM_NO_GLES2_VAO_SUPPORT #if GL_OES_vertex_array_object LogManager.Instance.Write("[GLES2] Binding VAO {0}.", _vao); GL.BindVertexArraysOES(1, &_vao); GLES2Config.CheckError(this); #endif #endif }
private void BuildMipmaps(PixelBox data) { int width, height, logW, logH, level; PixelBox scaled = data; scaled.Data = data.Data; scaled.Left = data.Left; scaled.Right = data.Right; scaled.Top = data.Top; scaled.Bottom = data.Bottom; scaled.Front = data.Front; scaled.Back = data.Back; width = data.Width; height = data.Height; logW = (int)System.Math.Log(width); logH = (int)System.Math.Log(height); level = (logW > logH ? logW : logH); for (int mip = 0; mip < level; mip++) { All glFormat = GLES2PixelUtil.GetGLOriginFormat(scaled.Format); All dataType = GLES2PixelUtil.GetGLOriginDataType(scaled.Format); GL.TexImage2D(this.faceTarget, mip, (int)glFormat, width, height, 0, glFormat, dataType, scaled.Data.Pin()); GLES2Config.GlCheckError(this); if (mip != 0) { scaled.Data = null; } if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } int sizeInBytes = PixelUtil.GetMemorySize(width, height, 1, data.Format); scaled = new PixelBox(width, height, 1, data.Format); scaled.Data = BufferBase.Wrap(new byte[sizeInBytes]); Image.Scale(data, scaled, ImageFilter.Linear); } //Delete the scaled data for the last level if (level > 0) { scaled.Data = null; } }
public void DetachDepthBuffer() { GL.BindFramebuffer(GLenum.Framebuffer, this._multiSampleFB > 0 ? this._multiSampleFB : this._fb); GLES2Config.GlCheckError(this); GL.FramebufferRenderbuffer(GLenum.Framebuffer, GLenum.DepthAttachment, GLenum.Renderbuffer, 0); GLES2Config.GlCheckError(this); GL.FramebufferRenderbuffer(GLenum.Framebuffer, GLenum.StencilAttachment, GLenum.Renderbuffer, 0); GLES2Config.GlCheckError(this); }
public GLES2FBOManager() { for (int x = 0; x < this.props.GetLength(0); x++) { this.props[x] = new FormatProperties(); } this.DetectFBOFormats(); GL.GenFramebuffers(1, ref this.tempFBO); GLES2Config.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="disposeManagedResources"> </param> protected override void dispose(bool disposeManagedResources) { if (!IsDisposed) { if (disposeManagedResources) { OpenGL.DeleteBuffers(1, ref this._bufferId); GLES2Config.GlCheckError(this); } } // If it is available, make the call to the // base class's Dispose(Boolean) method base.dispose(disposeManagedResources); }
public void Dispose() { this._manager.ReleaseRenderBuffer(this._depth); this._manager.ReleaseRenderBuffer(this._stencil); this._manager.ReleaseRenderBuffer(this._multiSampleColorBuffer); //Delete framebuffer object GL.DeleteFramebuffers(1, ref this._fb); GLES2Config.GlCheckError(this); if (this._multiSampleFB > 0) { GL.DeleteFramebuffers(1, ref this._multiSampleFB); GLES2Config.GlCheckError(this); } }
protected override void dispose(bool disposeManagedResources) { if (!IsDisposed) { if (disposeManagedResources) { } #if !AXIOM_NO_GLES2_VAO_SUPPORT #if GL_OES_vertex_array_object LogManager.Instance.Write("[GLES2] Deleting VAO {0}.", _vao); GL.DeleteVertexArraysOES(1, &_vao); GLES2Config.CheckError(this); #endif #endif } base.dispose(disposeManagedResources); }
public GLES2VertexDeclaration() { _vao = 0; #if !AXIOM_NO_GLES2_VAO_SUPPORT #if GL_OES_vertex_array_object GL.GenVertexArraysOES(1, &_vao); LogManager.Instance.Write("[GLES2] Created VAO {0}.", _vao); GLES2Config.CheckError(this); if (_vao != 0) { throw new AxiomException("[GLES2] Cannot create GL ES Vertex Array Object"); } #endif #endif }
public GLES2RenderBuffer(All format, int width, int height, int numSamples) : base(width, height, 1, GLES2PixelUtil.GetClosestAxiomFormat(format, (All)PixelFormat.A8R8G8B8), BufferUsage.WriteOnly) { GlInternalFormat = format; //Genearte renderbuffer GL.GenRenderbuffers(1, ref this.renderBufferID); GLES2Config.GlCheckError(this); //Bind it to FBO GL.BindRenderbuffer(All.Renderbuffer, this.renderBufferID); GLES2Config.GlCheckError(this); //Allocate storage for depth buffer if (numSamples > 0) { } else { GL.RenderbufferStorage(All.Renderbuffer, format, width, height); GLES2Config.GlCheckError(this); } }
public override void Bind(Graphics.RenderTarget target) { //Check if the render target is in the rendertarget.FBO map GLES2FrameBufferObject fbo = null; fbo = (GLES2FrameBufferObject)target["FBO"]; if (fbo != null) { fbo.Bind(); } else { //Old style context (window/pbuffer) or copying render texture //Ogre says 1 is screenbuffer on iOS as opposed to 0 on Android #if MONOTOUCH GL.BindFramebuffer(GLenum.Framebuffer, 1); #else GL.BindFramebuffer(GLenum.Framebuffer, 0); #endif GLES2Config.GlCheckError(this); } }
public GLES2HardwareVertexBuffer(HardwareBufferManagerBase manager, VertexDeclaration vertexDeclaration, int numVertices, BufferUsage usage, bool useShadowBuffer) : base(manager, vertexDeclaration, numVertices, usage, false, useShadowBuffer) { if (!useShadowBuffer) { throw new AxiomException("Only supported with shadowBuffer"); } var buffers = new int[1]; GL.GenBuffers(1, buffers); GLES2Config.GlCheckError(this); this._bufferID = buffers[0]; if (this._bufferID == 0) { throw new AxiomException("Cannot create GL ES vertex buffer"); } (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); }
/// <summary> /// </summary> protected override void UnlockImpl() { if (this._lockedToScratch) { if (this._scratchUploadOnUnlock) { // have to write the data back to vertex buffer this.WriteData(this._scratchOffset, this._scratchSize, this._scratchPtr, this._scratchOffset == 0 && this._scratchSize == sizeInBytes); } // deallocate from scratch buffer ((GLES2HardwareBufferManager)HardwareBufferManager.Instance).DeallocateScratch(this._scratchPtr); this._lockedToScratch = false; } else { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); if (!OpenGLOES.UnmapBuffer(All.ElementArrayBuffer)) { throw new AxiomException("Buffer data corrupted, please reload"); } } isLocked = false; }
/// <summary> /// </summary> /// <param name="offset"> </param> /// <param name="length"> </param> /// <param name="src"> </param> /// <param name="discardWholeBuffer"> </param> public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer) { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); // Update the shadow buffer if (useShadowBuffer) { var destData = shadowBuffer.Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal); Memory.Copy(src, destData, length); shadowBuffer.Unlock(); } var srcPtr = src.Ptr; if (offset == 0 && length == sizeInBytes) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), ref srcPtr, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { if (discardWholeBuffer) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } // Now update the real buffer OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(offset), new IntPtr(length), ref srcPtr); GLES2Config.GlCheckError(this); } if (src.Ptr != srcPtr) { LogManager.Instance.Write("[GLES2] HardwareIndexBuffer.WriteData - buffer pointer modified by GL.BufferData."); } }
/// <summary> /// </summary> protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); var srcPtr = new IntPtr(srcData.Ptr); // Update whole buffer if possible, otherwise normal if (lockStart == 0 && lockSize == sizeInBytes) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), srcPtr, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcPtr); GLES2Config.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
/// <summary> /// Initializes object (find suitable depth and stencil format). Must be called every time the bindings change. It will throw an exception if: -Attachment point 0 has no binding -Not all bound surfaces have the same size -Not all bound surfaces have the same internal format /// </summary> private void Initialize() { this._manager.ReleaseRenderBuffer(this._depth); this._manager.ReleaseRenderBuffer(this._stencil); this._manager.ReleaseRenderBuffer(this._multiSampleColorBuffer); //First buffer must be bound if (this._color[0].buffer == null) { throw new Core.AxiomException("Attachment 0 must have surface attached"); } // If we're doing multisampling, then we need another FBO which contains a // renderbuffer which is set up to multisample, and we'll blit it to the final // FBO afterwards to perform the multisample resolve. In that case, the // mMultisampleFB is bound during rendering and is the one with a depth/stencil var maxSupportedMRTs = Core.Root.Instance.RenderSystem.Capabilities.MultiRenderTargetCount; //Store basic stats int width = this._color[0].buffer.Width; int height = this._color[0].buffer.Height; GLenum format = this._color[0].buffer.GLFormat; //Bind simple buffer to add color attachments GL.BindFramebuffer(OpenTK.Graphics.ES20.All.Framebuffer, this._fb); GLES2Config.GlCheckError(this); //bind all attachment points to frame buffer for (int x = 0; x < maxSupportedMRTs; x++) { if (this._color[x].buffer != null) { if (this._color[x].buffer.Width != width || this._color[x].buffer.Height != height) { var ss = new StringBuilder(); ss.Append("Attachment " + x + " has incompatible size "); ss.Append(this._color[x].buffer.Width + "x" + this._color[x].buffer.Height); ss.Append(". It must be of the same as the size of surface 0, "); ss.Append(width + "x" + height.ToString()); ss.Append("."); throw new Core.AxiomException(ss.ToString()); } if (this._color[x].buffer.GLFormat != format) { throw new Core.AxiomException("Attachment " + x.ToString() + " has incompatible format."); } this._color[x].buffer.BindToFramebuffer((GLenum)((int)GLenum.ColorAttachment0) + x, this._color[x].zoffset); } else { //Detach GL.FramebufferRenderbuffer(GLenum.Framebuffer, (GLenum)((int)GLenum.ColorAttachment0) + x, GLenum.Renderbuffer, 0); GLES2Config.GlCheckError(this); } } //Now deal with depth/stencil if (this._multiSampleFB > 0) { //Bind multisample buffer GL.BindFramebuffer(GLenum.Framebuffer, this._multiSampleFB); GLES2Config.GlCheckError(this); //Create AA render buffer (color) //note, this can be shared too because we blit it to the final FBO //right after the render is finished this._multiSampleColorBuffer = this._manager.RequestRenderBuffer(format, width, height, this._numSamples); //Attach it, because we won't be attaching below and non-multisample has //actually been attached to other FBO this._multiSampleColorBuffer.buffer.BindToFramebuffer(GLenum.ColorAttachment0, this._multiSampleColorBuffer.zoffset); //depth & stencil will be dealt with below } /// Depth buffer is not handled here anymore. /// See GLES2FrameBufferObject::attachDepthBuffer() & RenderSystem::setDepthBufferFor() var bufs = new GLenum[Configuration.Config.MaxMultipleRenderTargets]; for (int x = 0; x < Configuration.Config.MaxMultipleRenderTargets; x++) { //Fill attached color buffers if (this._color[x].buffer != null) { bufs[x] = (GLenum)((int)GLenum.ColorAttachment0) + x; } else { bufs[x] = GLenum.None; } } //Check status var status = GL.CheckFramebufferStatus(GLenum.Framebuffer); GLES2Config.GlCheckError(this); //Possible todo: /*Port notes * Ogre leaves a comment indicating that the screen buffer for iOS * is 1 as opposed to 0 in the case of most other devices * I'd like to think that OpenTK takes care of this for us and have defaulted it * to 0 */ GL.BindFramebuffer(GLenum.Framebuffer, 0); GLES2Config.GlCheckError(this); switch (status) { case GLenum.FramebufferComplete: //All is good break; case GLenum.FramebufferUnsupported: throw new Core.AxiomException("All framebuffer formats with this texture internal format unsupported"); default: throw new Core.AxiomException("Framebuffer incomplete or other FBO status error"); } }
public override void BlitFromMemory(PixelBox src, BasicBox dstBox) { // Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case // - FBO is not supported // - Either source or target is luminance due doesn't looks like supported by hardware // - the source dimensions match the destination ones, in which case no scaling is needed //Ogre TODO: Check that extension is NOT available if (PixelUtil.IsLuminance(src.Format) || PixelUtil.IsLuminance(this.format) || (src.Width == dstBox.Width && src.Height == dstBox.Height && src.Depth == dstBox.Depth)) { base.BlitFromMemory(src, dstBox); return; } if (!Buffer.Contains(dstBox)) { throw new ArgumentOutOfRangeException("dstBox", "Destination box out of range"); } //For scoped deletion of conversion buffer PixelBox srcPB; BufferBase buf; //first, convert the srcbox to a OpenGL compatible pixel format if (GLES2PixelUtil.GetGLOriginFormat(src.Format) == 0) { //Conver to buffer intenral format buf = BufferBase.Wrap(new byte[PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, this.format)]); srcPB = new PixelBox(src.Width, src.Height, src.Depth, this.format, buf); PixelConverter.BulkPixelConversion(src, srcPB); } else { //No conversion needed srcPB = src; } //Create temporary texture to store source data int id = 0; All target = All.Texture2D; int width = GLES2PixelUtil.OptionalPO2(src.Width); int height = GLES2PixelUtil.OptionalPO2(src.Height); All format = GLES2PixelUtil.GetClosestGLInternalFormat(src.Format); All datatype = GLES2PixelUtil.GetGLOriginDataType(src.Format); //Generate texture name GL.GenTextures(1, ref id); GLES2Config.GlCheckError(this); //Set texture type GL.BindTexture(target, id); GLES2Config.GlCheckError(this); //Allocate texture memory GL.TexImage2D(target, 0, (int)format, width, height, 0, format, datatype, IntPtr.Zero); GLES2Config.GlCheckError(this); var tex = new GLES2TextureBuffer(string.Empty, target, id, width, height, format, (All)src.Format, 0, 0, BufferUsage.StaticWriteOnly, false, false, 0); //Upload data to 0,0,0 in temprary texture var tempTarget = new BasicBox(0, 0, 0, srcPB.Width, srcPB.Height, srcPB.Depth); tex.Upload(srcPB, tempTarget); //Blit this.BlitFromTexture(tex, tempTarget, dstBox); GLES2Config.GlCheckError(this); }
public GLES2TextureBuffer(string baseName, All target, int id, int width, int height, All internalFormat, All format, int face, int level, BufferUsage usage, bool crappyCard, bool writeGamma, int fsaa) : base(0, 0, 0, PixelFormat.Unknown, usage) { this.target = target; this.textureID = id; this.face = face; this.level = level; this.softwareMipmap = crappyCard; GLES2Config.GlCheckError(this); GL.BindTexture(target, this.textureID); GLES2Config.GlCheckError(this); //Get face identifier this.faceTarget = this.target; if (this.target == All.TextureCubeMap) { this.faceTarget = All.TextureCubeMapPositiveX + face; } //Calculate the width and height of the texture at this mip level this.width = this.level == 0 ? width : (int)(width / Math.Utility.Pow(2, level)); this.height = this.level == 0 ? height : (int)(height / Math.Utility.Pow(2, level)); if (this.width < 1) { this.width = 1; } if (this.height < 1) { this.height = 1; } //Only 2D is supporte so depth is always 1 depth = 1; GlInternalFormat = internalFormat; this.format = GLES2PixelUtil.GetClosestAxiomFormat(internalFormat, format); rowPitch = this.width; slicePitch = this.height * this.width; sizeInBytes = PixelUtil.GetMemorySize(this.width, this.height, depth, this.format); //Setup a pixel box Buffer = new PixelBox(this.width, this.height, depth, this.format); if (this.width == 0 || this.height == 0 || depth == 0) { //We are invalid, do not allocat a buffer return; } if (((TextureUsage)usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget) { //Create render target for each slice for (int zoffset = 0; zoffset < depth; zoffset++) { var name = "rtt/ " + GetHashCode() + "/" + baseName; var rtarget = new GLES2SurfaceDesc { buffer = this, zoffset = zoffset }; var trt = GLES2RTTManager.Instance.CreateRenderTexture(name, rtarget, writeGamma, fsaa); this.sliceTRT.Add(trt); Core.Root.Instance.RenderSystem.AttachRenderTarget(this.sliceTRT[zoffset]); } } }
protected override void createInternalResources() { //Conver to nearest power of two size if require this.width = GLES2PixelUtil.OptionalPO2(Width); this.height = GLES2PixelUtil.OptionalPO2(Height); this.depth = GLES2PixelUtil.OptionalPO2(Depth); //Adjust format if required format = TextureManager.Instance.GetNativeFormat(textureType, Format, usage); //Check requested number of mipmaps int maxMips = GLES2PixelUtil.GetMaxMipmaps(this.width, this.height, this.depth, format); if (PixelUtil.IsCompressed(format) && (mipmapCount == 0)) { requestedMipmapCount = 0; } mipmapCount = requestedMipmapCount; if (mipmapCount > maxMips) { mipmapCount = maxMips; } //Generate texture name GL.GenTextures(1, ref this.textureID); GLES2Config.GlCheckError(this); //Set texture name GL.BindTexture(this.GLES2TextureTarget, this.textureID); GLES2Config.GlCheckError(this); //Set some misc default parameters, tehse can of course be changed later GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureMinFilter, (int)GLenum.Nearest); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureMagFilter, (int)GLenum.Nearest); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureWrapS, (int)GLenum.ClampToEdge); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureWrapT, (int)GLenum.ClampToEdge); GLES2Config.GlCheckError(this); //If we can do automip generation and the user desires this, do so mipmapsHardwareGenerated = Root.Instance.RenderSystem.Capabilities.HasCapability(Capabilities.HardwareMipMaps) && !PixelUtil.IsCompressed(format); //Ogre FIXME: For some reason this is crashing on iOS 5 #if !MONOTOUCH && ANDROID if ((usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap && requestedMipmapCount > 0 && mipmapsHardwareGenerated && (textureType != Graphics.TextureType.CubeMap)) { GL.GenerateMipmap(this.GLES2TextureTarget); GLES2Config.GlCheckError(this); } #endif //Allocate internal buffer so that glTexSubImageXD can be used //INternal format GLenum glformat = GLES2PixelUtil.GetClosestGLInternalFormat(format, hwGamma); GLenum dataType = GLES2PixelUtil.GetGLOriginDataType(format); int width = Width; int height = Height; int depth = Depth; if (PixelUtil.IsCompressed(format)) { //Compressed formats int size = PixelUtil.GetMemorySize(Width, Height, Depth, Format); // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not // accept a 0 pointer like normal glTexImageXD // Run through this process for every mipmap to pregenerate mipmap pyramid var tmpData = new IntPtr(); for (int mip = 0; mip < mipmapCount; mip++) { size = PixelUtil.GetMemorySize(width, height, depth, Format); switch (textureType) { case TextureType.OneD: case TextureType.TwoD: GL.CompressedTexImage2D(GLenum.Texture2D, mip, glformat, width, height, 0, size, tmpData); GLES2Config.GlCheckError(this); break; case TextureType.CubeMap: for (int face = 0; face < 6; face++) { GL.CompressedTexImage2D((GLenum)((int)GLenum.TextureCubeMapPositiveX + face), mip, glformat, width, height, 0, size, tmpData); GLES2Config.GlCheckError(this); } break; case TextureType.ThreeD: break; default: break; } if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1) { depth = depth / 2; } } tmpData = IntPtr.Zero; } else { //Run through this process to pregenerate mipmap pyramid for (int mip = 0; mip < mipmapCount; mip++) { //Normal formats switch (textureType) { case TextureType.OneD: case TextureType.TwoD: GL.TexImage2D(GLenum.Texture2D, mip, (int)glformat, width, height, 0, glformat, dataType, new IntPtr()); GLES2Config.GlCheckError(this); break; case TextureType.CubeMap: for (int face = 0; face < 6; face++) { GL.TexImage2D(GLenum.TextureCubeMapPositiveX + face, mip, (int)glformat, width, height, 0, glformat, dataType, new IntPtr()); GLES2Config.GlCheckError(this); } break; case TextureType.ThreeD: default: break; } if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } } } this.CreateSurfaceList(); //Get final internal format base.format = this.GetBuffer(0, 0).Format; }
protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { if (IsLocked) { throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked."); } BufferBase retPtr; var glBufManager = (HardwareBufferManager.Instance as GLES2HardwareBufferManager); //Try to use scratch buffers for smaller buffers if (length < glBufManager.MapBufferThreshold) { retPtr = glBufManager.AllocateScratch(length); if (retPtr != null) { this._lockedToScratch = true; this._scratchOffset = offset; this._scratchSize = length; this._scratchPtr = retPtr; this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly); if (locking != BufferLocking.Discard) { //have to read back the data before returning the pointer this.ReadData(offset, length, retPtr); } } } else { throw new AxiomException("Invalid Buffer lockSize"); } if (retPtr == null) { GLenum access = GLenum.Zero; (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); if (locking == BufferLocking.Discard) { //Discard the buffer GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) == BufferUsage.WriteOnly) { access = GLenum.WriteOnlyOes; } var pbuffer = GL.Oes.MapBuffer(GLenum.ArrayBuffer, access); GLES2Config.GlCheckError(this); if (pbuffer == IntPtr.Zero) { throw new AxiomException("Vertex Buffer: Out of memory"); } //return offsetted retPtr = BufferBase.Wrap(pbuffer, sizeInBytes) + offset; this._lockedToScratch = false; } isLocked = true; return(retPtr); }
protected override void freeInternalResources() { this.surfaceList.Clear(); GL.DeleteTextures(1, ref this.textureID); GLES2Config.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="offset"> </param> /// <param name="length"> </param> /// <param name="locking"> </param> /// <returns> </returns> protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { All access = 0; if (isLocked) { throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked"); } BufferBase retPtr = null; if (length < MapBufferThreshold) { retPtr = ((GLES2HardwareBufferManager)HardwareBufferManager.Instance).AllocateScratch(length); if (retPtr != null) { this._lockedToScratch = true; this._scratchOffset = offset; this._scratchSize = length; this._scratchPtr = retPtr; this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly); if (locking != BufferLocking.Discard) { this.ReadData(offset, length, retPtr); } } } else { throw new AxiomException("Invalid Buffer lockSize"); } if (retPtr == null) { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); // Use glMapBuffer if (locking == BufferLocking.Discard) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) != 0) { access = All.WriteOnlyOes; } IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access); GLES2Config.GlCheckError(this); if (pBuffer == IntPtr.Zero) { throw new AxiomException("Index Buffer: Out of memory"); } unsafe { // return offset retPtr = BufferBase.Wrap(pBuffer, sizeInBytes); } this._lockedToScratch = false; } isLocked = true; return(retPtr); }
public override void BindToFramebuffer(All attachment, int zoffset) { GL.FramebufferRenderbuffer(All.Framebuffer, attachment, All.Renderbuffer, this.renderBufferID); GLES2Config.GlCheckError(this); }
protected override void dispose(bool disposeManagedResources) { GL.DeleteRenderbuffers(1, ref this.renderBufferID); GLES2Config.GlCheckError(this); base.dispose(disposeManagedResources); }