예제 #1
0
        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);
            }
        }
예제 #2
0
        ///<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);
            }
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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;
            }
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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
        }
예제 #9
0
        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;
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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);
        }
예제 #15
0
        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
        }
예제 #16
0
        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);
            }
        }
예제 #17
0
        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);
            }
        }
예제 #18
0
        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);
        }
예제 #19
0
 /// <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;
 }
예제 #20
0
        /// <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.");
            }
        }
예제 #21
0
        /// <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;
            }
        }
예제 #22
0
        /// <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");
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
        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]);
                }
            }
        }
예제 #25
0
        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;
        }
예제 #26
0
        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);
        }
예제 #27
0
 protected override void freeInternalResources()
 {
     this.surfaceList.Clear();
     GL.DeleteTextures(1, ref this.textureID);
     GLES2Config.GlCheckError(this);
 }
예제 #28
0
        /// <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);
        }
예제 #29
0
 public override void BindToFramebuffer(All attachment, int zoffset)
 {
     GL.FramebufferRenderbuffer(All.Framebuffer, attachment, All.Renderbuffer, this.renderBufferID);
     GLES2Config.GlCheckError(this);
 }
예제 #30
0
 protected override void dispose(bool disposeManagedResources)
 {
     GL.DeleteRenderbuffers(1, ref this.renderBufferID);
     GLES2Config.GlCheckError(this);
     base.dispose(disposeManagedResources);
 }