public GLESHardwareIndexBuffer(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); GLESConfig.GlCheckError(this); if (this._bufferId == 0) { throw new AxiomException("Cannot create GL index buffer"); } OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLESConfig.GlCheckError(this); OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); }
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(), GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } else { if (discardWholeBuffer) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(offset), new IntPtr(length), src.Pin()); GLESConfig.GlCheckError(this); } }
/// <summary> /// </summary> /// <param name="p"> </param> internal void CopyFromFramebuffer(int p) { OpenGL.BindBuffer(All.Texture2D, this._textureId); GLESConfig.GlCheckError(this); OpenGL.CopyTexSubImage2D(All.Texture2D, this._level, 0, 0, 0, 0, Width, Height); GLESConfig.GlCheckError(this); }
/// <summary> /// Internal method to create a warning texture (bound when a texture unit is blank) /// </summary> protected void CreateWarningTexture() { // Generate warning texture int width = 8; int height = 8; // TODO convert to 5_6_5 unsafe { int *data = stackalloc int[width * height]; // 0xXXRRGGBB //yellow / black stripes for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { data[y * width + x] = (((x + y) % 8) < 4) ? 0x000000 : 0xFFFF00; } } // Create GL resource OpenGL.GenTextures(1, ref this._warningTextureID); GLESConfig.GlCheckError(this); OpenGL.BindTexture(All.Texture2D, this._warningTextureID); GLESConfig.GlCheckError(this); OpenGL.TexImage2D(All.Texture2D, 0, (int)All.Rgb, width, height, 0, All.Rgb, All.UnsignedByte, (IntPtr)data); GLESConfig.GlCheckError(this); } }
protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); (Root.Instance.RenderSystem as GLESRenderSystem).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(), GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } else { //Ogre FIXME: GPU frequently stalls here - DJR GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcData.Pin()); GLESConfig.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
/// <summary> /// Bind FrameBufferObject /// </summary> public void Bind() { /// Bind it to FBO int fb = this._multiSampleFB != 0 ? this._multiSampleFB : this._fb; OpenGLOES.BindFramebuffer(All.FramebufferOes, fb); GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="attachment"> </param> public override void UnbindSurface(int attachment) { this._fbo.UnbindSurface(attachment); GLESConfig.GlCheckError(attachment); Width = this._fbo.Width; Height = this._fbo.Height; }
protected static void BuildMipmaps(PixelBox data) { int width = 0; int height = 0; int logW = 0; int logH = 0; int level = 0; 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; All format = GLESPixelUtil.GetGLOriginFormat(data.Format); All dataType = GLESPixelUtil.GetGLOriginDataType(data.Format); width = data.Width; height = data.Height; logW = ComputeLog(width); logH = ComputeLog(height); level = (logW > logH ? logW : logH); for (int mip = 0; mip <= level; mip++) { format = GLESPixelUtil.GetGLOriginFormat(scaled.Format); dataType = GLESPixelUtil.GetGLOriginDataType(scaled.Format); OpenGL.TexImage2D(All.Texture2D, mip, (int)format, width, height, 0, format, dataType, scaled.Data); GLESConfig.GlCheckError(null); if (mip != 0) { scaled.Data = IntPtr.Zero; } if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } int sizeInBytes = PixelUtil.GetMemorySize(width, height, 1, data.Format); scaled = new PixelBox(width, height, 1, data.Format); var dataarr = new byte[sizeInBytes]; scaled.Data = Memory.PinObject(dataarr); Image.Scale(data, scaled, ImageFilter.Linear); } }
protected override void dispose(bool disposeManagedResources) { GL.DeleteBuffers(1, ref this._bufferID); GLESConfig.GlCheckError(this); (Root.Instance.RenderSystem as GLESRenderSystem).DeleteGLBuffer(GLenum.ArrayBuffer, this._bufferID); base.dispose(disposeManagedResources); }
/// <summary> /// </summary> /// <param name="disposeManagedResources"> </param> protected override void dispose(bool disposeManagedResources) { // Unregister with group manager ResourceGroupManager.Instance.UnregisterResourceManager(base.ResourceType); // Delete warning texture OpenGL.DeleteTextures(1, ref this._warningTextureID); GLESConfig.GlCheckError(this); base.dispose(disposeManagedResources); }
/// <summary> /// </summary> /// <param name="support"> </param> public GLESTextureManager(GLESSupport support) { this._glSupport = support; WarningTextureID = 0; GLESConfig.GlCheckError(this); // Register with group manager ResourceGroupManager.Instance.RegisterResourceManager(base.ResourceType, this); CreateWarningTexture(); }
/// <summary> /// </summary> public GLESFBORTTManager() : base() { LogManager.Instance.Write("FBO CTOR ENTER"); this._renderBuffer = new Dictionary <RBFormat, RBRef>(); TemporaryFBO = 0; DetectFBOFormats(); OpenGLOES.GenFramebuffers(1, ref this._tempFbo); GLESConfig.GlCheckError(this); LogManager.Instance.Write("FBO CTOR EXIT"); }
/// <summary> /// </summary> /// <param name="attachment"> </param> /// <param name="target"> </param> public override void BindSurface(int attachment, RenderTexture target) { /// Check if the render target is in the rendertarget->FBO map var fbobj = target["FBO"] as GLESFrameBufferObject; Utilities.Contract.Requires(fbobj != null); this._fbo.BindSurface(attachment, fbobj.GetSurface(0)); GLESConfig.GlCheckError(this); Width = this._fbo.Width; Height = this._fbo.Height; }
/// <summary> /// </summary> /// <param name="name"> </param> /// <param name="target"> </param> /// <param name="id"> </param> /// <param name="width"> </param> /// <param name="height"> </param> /// <param name="format"> </param> /// <param name="face"> </param> /// <param name="level"> </param> /// <param name="usage"> </param> /// <param name="crappyCard"> </param> /// <param name="writeGamma"> </param> /// <param name="fsaa"> </param> public GLESTextureBuffer(string basename, All targetfmt, int id, int width, int height, int format, int face, int level, BufferUsage usage, bool crappyCard, bool writeGamma, int fsaa) : base(0, 0, 0, Media.PixelFormat.Unknown, usage) { this._target = targetfmt; this._textureId = id; this._face = face; this._level = level; this._softwareMipmap = crappyCard; GLESConfig.GlCheckError(this); OpenGL.BindTexture(All.Texture2D, this._textureId); GLESConfig.GlCheckError(this); // Get face identifier this._faceTarget = this._target; // TODO verify who get this Width = width; Height = height; Depth = 1; _glInternalFormat = (All)format; Format = GLESPixelUtil.GetClosestAxiomFormat(_glInternalFormat); RowPitch = Width; SlicePitch = Height * Width; sizeInBytes = PixelUtil.GetMemorySize(Width, Height, Depth, Format); // Set up a pixel box _buffer = new PixelBox(Width, Height, Depth, Format); if (Width == 0 || Height == 0 || Depth == 0) { /// We are invalid, do not allocate a buffer return; } // Is this a render target? if (((int)Usage & (int)TextureUsage.RenderTarget) != 0) { // Create render target for each slice for (int zoffset = 0; zoffset < Depth; zoffset++) { string name = string.Empty; name = "rtt/" + GetHashCode() + "/" + basename; var target = new GLESSurfaceDescription(); target.Buffer = this; target.ZOffset = zoffset; RenderTexture trt = GLESRTTManager.Instance.CreateRenderTexture(name, target, writeGamma, fsaa); this._sliceTRT.Add(trt); Root.Instance.RenderSystem.AttachRenderTarget(this._sliceTRT[zoffset]); } } }
/// <summary> /// </summary> /// <param name="manager"> </param> /// <param name="fsaa"> </param> public GLESFrameBufferObject(GLESFBORTTManager manager, int fsaa) { /// Generate framebuffer object OpenGLOES.GenFramebuffers(1, ref this._fb); GLESConfig.GlCheckError(this); this._depth = new GLESSurfaceDescription(); this._stencil = new GLESSurfaceDescription(); for (int x = 0; x < Configuration.Config.MaxMultipleRenderTargets; x++) { this._color[x] = new GLESSurfaceDescription(); } }
/// <summary> /// </summary> /// <param name="disposeManagedResources"> </param> protected override void dispose(bool disposeManagedResources) { if (!IsDisposed) { if (disposeManagedResources) { OpenGL.DeleteBuffers(1, ref this._bufferId); GLESConfig.GlCheckError(this); } } // If it is available, make the call to the // base class's Dispose(Boolean) method base.dispose(disposeManagedResources); }
/// <summary> /// </summary> public void Dispose() { Manager.ReleaseRenderbuffer(this._depth); Manager.ReleaseRenderbuffer(this._stencil); Manager.ReleaseRenderbuffer(this._multisampleColorBuffer); /// Delete framebuffer object OpenGLOES.DeleteFramebuffers(1, ref this._fb); GLESConfig.GlCheckError(this); if (this._multiSampleFB != 0) { OpenGLOES.DeleteFramebuffers(1, ref this._multiSampleFB); } GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="format"> </param> /// <param name="width"> </param> /// <param name="height"> </param> /// <param name="numSamples"> </param> public GLESRenderBuffer(All format, int width, int height, int numSamples) : base(width, height, 1, GLESPixelUtil.GetClosestAxiomFormat(format), BufferUsage.WriteOnly) { _glInternalFormat = format; /// Generate renderbuffer OpenGLOES.GenRenderbuffers(1, ref this._renderbufferID); GLESConfig.GlCheckError(this); /// Bind it to FBO OpenGLOES.BindRenderbuffer(All.RenderbufferOes, this._renderbufferID); GLESConfig.GlCheckError(this); /// Allocate storage for depth buffer if (numSamples <= 0) { OpenGLOES.RenderbufferStorage(All.RenderbufferOes, format, width, height); GLESConfig.GlCheckError(this); } }
/// <summary> /// Bind a certain render target if it is a FBO. If it is not a FBO, bind the main frame buffer. /// </summary> /// <param name="target"> </param> public override void Bind(Graphics.RenderTarget target) { /// Check if the render target is in the rendertarget->FBO map GLESFrameBufferObject fbo = null; fbo = target["FBO"] as GLESFrameBufferObject; if (fbo != null) { fbo.Bind(); } else { // Old style context (window/pbuffer) or copying render texture #if AXIOM_PLATFORM_IPHONE // The screen buffer is 1 on iPhone OpenGLOES.BindFramebuffer(All.FramebufferOes, 1); #else OpenGLOES.BindFramebuffer(All.FramebufferOes, 0); #endif GLESConfig.GlCheckError(this); } }
public GLESHardwareVertexBuffer(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); GLESConfig.GlCheckError(this); this._bufferID = buffers[0]; if (this._bufferID == 0) { throw new AxiomException("Cannot create GL ES vertex buffer"); } (Root.Instance.RenderSystem as GLESRenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLESConfig.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, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } else { OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcPtr); GLESConfig.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
/// <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 ((GLESHardwareBufferManager)HardwareBufferManager.Instance).DeallocateScratch(this._scratchPtr); this._lockedToScratch = false; } else { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLESConfig.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); GLESConfig.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, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } else { if (discardWholeBuffer) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } // Now update the real buffer OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(offset), new IntPtr(length), ref srcPtr); GLESConfig.GlCheckError(this); } if (src.Ptr != srcPtr) { LogManager.Instance.Write("[GLES2] HardwareIndexBuffer.WriteData - buffer pointer modified by GL.BufferData."); } }
/// <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 = ((GLESHardwareBufferManager)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); GLESConfig.GlCheckError(this); // Use glMapBuffer if (locking == BufferLocking.Discard) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLESHardwareBufferManager.GetGLUsage(usage)); GLESConfig.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) != 0) { access = All.WriteOnlyOes; } IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access); GLESConfig.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); }
/// <summary> /// Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. /// </summary> private void DetectFBOFormats() { // Try all formats, and report which ones work as target int fb = 0, tid = 0; All target = All.Texture2D; for (int x = 0; x < (int)Media.PixelFormat.Count; x++) { LogManager.Instance.Write("[GLES] [DEBUG] testing PixelFormat : {0}", (Media.PixelFormat)x); this._props[x] = new FormatProperties(); this._props[x].Modes = new List <FormatProperties.Mode>(); this._props[x].IsValid = false; // Fetch GL format token All fmt = GLESPixelUtil.GetClosestGLInternalFormat((Media.PixelFormat)x); LogManager.Instance.Write("[GLES] [DEBUG] fmt={0}", fmt); if (fmt == All.Zero && x != 0) { continue; } // No test for compressed formats if (PixelUtil.IsCompressed((Media.PixelFormat)x)) { continue; } // Create and attach framebuffer OpenGLOES.GenRenderbuffers(1, ref fb); GLESConfig.GlCheckError(this); OpenGLOES.BindFramebuffer(All.FramebufferOes, fb); GLESConfig.GlCheckError(this); if (fmt != All.Zero) { // Create and attach texture OpenGL.GenTextures(1, ref tid); GLESConfig.GlCheckError(this); OpenGL.BindTexture(target, tid); GLESConfig.GlCheckError(this); // Set some default parameters OpenGL.TexParameterx(target, All.TextureMinFilter, (int)All.LinearMipmapNearest); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureMagFilter, (int)All.Nearest); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureWrapS, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureWrapT, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexImage2D(target, 0, (int)fmt, ProbeSize, ProbeSize, 0, fmt, All.UnsignedByte, IntPtr.Zero); GLESConfig.GlCheckError(this); OpenGLOES.FramebufferTexture2D(All.FramebufferOes, All.ColorAttachment0Oes, target, tid, 0); GLESConfig.GlCheckError(this); } // Check status All status = OpenGLOES.CheckFramebufferStatus(All.FramebufferOes); GLESConfig.GlCheckError(this); LogManager.Instance.Write("[GLES] [DEBUG] status={0}", status); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if (fmt == 0 || status == All.FramebufferCompleteOes) { this._props[x].IsValid = true; var str = new StringBuilder(); str.Append("FBO " + PixelUtil.GetFormatName((Media.PixelFormat)x) + " depth/stencil support: "); // For each depth/stencil formats for (int depth = 0; depth < DepthFormats.Length; ++depth) { if (DepthFormats[depth] != All.Depth24Stencil8Oes) { // General depth/stencil combination for (int stencil = 0; stencil < StencilFormats.Length; ++stencil) { if (TryFormat(DepthFormats[depth], StencilFormats[stencil])) { /// Add mode to allowed modes str.Append("D" + DepthBits[depth] + "S" + StencilBits[stencil] + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = stencil; this._props[x].Modes.Add(mode); } } //end for stencil } //end if else { // Packed depth/stencil format if (TryPacketFormat(DepthFormats[depth])) { /// Add mode to allowed modes str.Append("Packed-D" + DepthBits[depth] + "S8" + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = 0; //unused this._props[x].Modes.Add(mode); } } } //end for depth LogManager.Instance.Write(str.ToString()); } //end if // Delete texture and framebuffer #if AXIOM_PLATFORM_IPHONE // The screen buffer is 1 on iPhone OpenGLOES.BindFramebuffer(All.FramebufferOes, 1); #else OpenGLOES.BindFramebuffer(All.FramebufferOes, 0); #endif GLESConfig.GlCheckError(this); OpenGLOES.DeleteFramebuffers(1, ref fb); GLESConfig.GlCheckError(this); if (fmt != 0) { OpenGL.DeleteTextures(1, ref tid); } } //end for pixelformat count string fmtstring = string.Empty; for (int x = 0; x < (int)Media.PixelFormat.Count; x++) { if (this._props[x].IsValid) { fmtstring += PixelUtil.GetFormatName((Media.PixelFormat)x); } } LogManager.Instance.Write("[GLES] : Valid FBO targets " + fmtstring); }
/// <summary> /// </summary> /// <param name="attachment"> </param> /// <param name="zOffset"> </param> public override void BindToFramebuffer(All attachment, int zOffset) { Utilities.Contract.Requires(zOffset < Depth); OpenGLOES.FramebufferRenderbuffer(All.FramebufferOes, attachment, All.RenderbufferOes, this._renderbufferID); GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="data"> </param> /// <param name="dest"> </param> protected override void Upload(PixelBox data, BasicBox dest) { OpenGL.BindTexture(this._target, this._textureId); GLESConfig.GlCheckError(this); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != Format || !data.IsConsecutive) { throw new AxiomException("Compressed images must be consecutive, in the source format"); } if (data.Format != Format || !data.IsConsecutive) { throw new AxiomException("Compressed images must be consecutive, in the source format."); } All format = GLESPixelUtil.GetClosestGLInternalFormat(Format); // Data must be consecutive and at beginning of buffer as PixelStorei not allowed // for compressed formats if (dest.Left == 0 && dest.Top == 0) { OpenGL.CompressedTexImage2D(All.Texture2D, this._level, format, dest.Width, dest.Height, 0, data.ConsecutiveSize, data.Data); } else { OpenGL.CompressedTexSubImage2D(All.Texture2D, this._level, dest.Left, dest.Top, dest.Width, dest.Height, format, data.ConsecutiveSize, data.Data); } GLESConfig.GlCheckError(this); } else if (this._softwareMipmap) { if (data.Width != data.RowPitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (data.Height * data.Width != data.SlicePitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } OpenGL.PixelStore(All.UnpackAlignment, 1); GLESConfig.GlCheckError(this); BuildMipmaps(data); } else { if (data.Width != data.RowPitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (data.Height * data.Width != data.SlicePitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (((data.Width * PixelUtil.GetNumElemBytes(data.Format)) & 3) != 0) { // Standard alignment of 4 is not right OpenGL.PixelStore(All.UnpackAlignment, 1); GLESConfig.GlCheckError(this); } All form = GLESPixelUtil.GetGLOriginFormat(data.Format); All pix = GLESPixelUtil.GetGLOriginDataType(data.Format); GLESConfig.GlCheckError(this); GL.TexSubImage2D(this._faceTarget, this._level, dest.Left, dest.Top, dest.Width, dest.Height, GLESPixelUtil.GetGLOriginFormat(data.Format), GLESPixelUtil.GetGLOriginDataType(data.Format), data.Data); GLESConfig.GlCheckError(this); } OpenGL.PixelStore(All.UnpackAlignment, 4); GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> /// <param name="attachment"> </param> /// <param name="zOffset"> </param> public override void BindToFramebuffer(All attachment, int zOffset) { Axiom.Utilities.Contract.Requires(zOffset < Depth, "GLESTextureBuffer.BindToFramebuffer, z offset must be smaller then depth"); OpenGL.Oes.FramebufferTexture2D(All.FramebufferOes, attachment, this._faceTarget, this._textureId, this._level); GLESConfig.GlCheckError(this); }
/// <summary> /// </summary> protected override void createInternalResources() { // Convert to nearest power-of-two size if required Width = GLESPixelUtil.OptionalPO2(Width); Height = GLESPixelUtil.OptionalPO2(Height); Depth = GLESPixelUtil.OptionalPO2(Depth); //adjust format if required Format = TextureManager.Instance.GetNativeFormat(Graphics.TextureType.TwoD, Format, Usage); // Check requested number of mipmaps int maxMips = GLESPixelUtil.GetMaxMipmaps(Width, Height, Depth, Format); if (PixelUtil.IsCompressed(Format) && _mipmapCount == 0) { RequestedMipmapCount = 0; } _mipmapCount = RequestedMipmapCount; if (_mipmapCount > maxMips) { _mipmapCount = maxMips; } // Generate texture name OpenGL.GenTextures(1, ref this._textureID); GLESConfig.GlCheckError(this); // Set texture type OpenGL.BindTexture(All.Texture2D, this._textureID); GLESConfig.GlCheckError(this); // Set some misc default parameters, these can of course be changed later OpenGL.TexParameter(All.Texture2D, All.TextureMinFilter, (int)All.LinearMipmapNearest); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureMagFilter, (int)All.Nearest); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureWrapS, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureWrapT, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); // If we can do automip generation and the user desires this, do so MipmapsHardwareGenerated = Root.Instance.RenderSystem.HardwareCapabilities.HasCapability(Capabilities.HardwareMipMaps) && !PixelUtil.IsCompressed(Format); if ((Usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap && RequestedMipmapCount > 0 && MipmapsHardwareGenerated) { OpenGL.TexParameter(All.Texture2D, All.GenerateMipmap, (int)All.True); GLESConfig.GlCheckError(this); } // Allocate internal buffer so that TexSubImageXD can be used // Internal format All format = GLESPixelUtil.GetClosestGLInternalFormat(Format, HardwareGammaEnabled); 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 byte[size]; IntPtr tmpDataptr = Memory.PinObject(tmpData); for (int mip = 0; mip <= MipmapCount; mip++) { size = PixelUtil.GetMemorySize(Width, Height, Depth, Format); OpenGL.CompressedTexImage2D(All.Texture2D, mip, format, width, height, 0, size, tmpDataptr); GLESConfig.GlCheckError(this); if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1) { depth = depth / 2; } } Memory.UnpinObject(tmpData); } else { // Run through this process to pregenerate mipmap pyramid for (int mip = 0; mip <= MipmapCount; mip++) { OpenGL.TexImage2D(All.Texture2D, mip, (int)format, width, height, 0, format, All.UnsignedByte, IntPtr.Zero); GLESConfig.GlCheckError(this); if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } } } CreateSurfaceList(); // Get final internal format Format = GetBuffer(0, 0).Format; }
/// <summary> /// </summary> protected override void freeInternalResources() { this._surfaceList.Clear(); OpenGL.DeleteTextures(1, ref this._textureID); GLESConfig.GlCheckError(this); }