protected override void Download(PixelBox data) { #if GL_NV_get_tex_image if (data.Width != Width || data.Height != Height || data.Depth != Depth) { throw new Core.AxiomException("only download of entire buffer is supported by GL"); } GL.BindTexture(this.target, this.textureID); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != format || !data.IsConsecutive) { throw new Core.AxiomException("Compressed images must be consecutive, in the source format"); } GL.GetCompressedTexImageNV(this.faceTarget, this.level, data.Data); } else { if ((data.Width * PixelUtil.GetNumElemBytes(data.Format) & 3) != 0) { //Standard alignment of 4 is not right GL.PixelStore(Glenum.PackAlignment, 1); } //We can only get the entire texture GL.GetTexImageNV(this.faceTarget, this.level, GLES2PixelUtil.GetGLOriginFormat(data.Format), GLES2PixelUtil.GetGLOriginDataType(data.Format), data.Data); //Restore defaults GL.PixelStore(Glenum.PackAlignment, 4); } #else throw new Core.AxiomException("Downloading texture buffers is not supported by OpenGL ES"); #endif }
public void DrawBatch20(SpriteSortMode sortMode) { // nothing to do if (_batchItemList.Count == 0) { return; } // sort the batch items switch (sortMode) { case SpriteSortMode.Texture: _batchItemList.Sort(CompareTexture); break; case SpriteSortMode.FrontToBack: _batchItemList.Sort(CompareDepth); break; case SpriteSortMode.BackToFront: _batchItemList.Sort(CompareReverseDepth); break; } // make sure an old draw isn't still going on. // cross fingers, commenting this out!! //GL20.Flush(); GL20.EnableVertexAttribArray(attributePosition); GL20.EnableVertexAttribArray(attributeTexCoord); int size = VertexPosition2ColorTexture.GetSize(); GL20.VertexAttribPointer(attributePosition, 2, All20.Float, false, size, _vertexHandle.AddrOfPinnedObject()); GL20.VertexAttribPointer(attributeTexCoord, 2, All20.Float, false, size, (IntPtr)((uint)_vertexHandle.AddrOfPinnedObject() + (uint)(sizeof(float) * 2 + sizeof(uint)))); // GL11.VertexPointer(2,All11.Float,size,_vertexHandle.AddrOfPinnedObject() ); // GL11.ColorPointer(4, All11.UnsignedByte,size,(IntPtr)((uint)_vertexHandle.AddrOfPinnedObject()+(uint)(sizeof(float)*2))); // GL11.TexCoordPointer(2, All11.Float,size,(IntPtr)((uint)_vertexHandle.AddrOfPinnedObject()+(uint)(sizeof(float)*2+sizeof(uint))) ); // setup the vertexArray array int startIndex = 0; int index = 0; int texID = -1; Color lastTint = new Color(0.0f, 0.0f, 0.0f, 0.0f); // make sure the vertexArray has enough space if (_batchItemList.Count * 4 > _vertexArray.Length) { ExpandVertexArray(_batchItemList.Count); } foreach (SpriteBatchItem item in _batchItemList) { //Tint Color Vector4 vtint = item.Tint.ToVector4(); vtint /= 255; // GL20.VertexAttrib4(attributeTint,vtint.X, vtint.Y, vtint.Z, vtint.W); // if the texture changed, we need to flush and bind the new texture if (item.TextureID != texID || item.Tint != lastTint) { FlushVertexArray20(startIndex, index); startIndex = index; texID = item.TextureID; lastTint = item.Tint; GL20.ActiveTexture(All20.Texture0); GL20.BindTexture(All20.Texture2D, texID); GL20.Uniform1(texID, 0); GL20.VertexAttrib4(attributeTint, vtint.X, vtint.Y, vtint.Z, vtint.W); } // store the SpriteBatchItem data in our vertexArray _vertexArray[index++] = item.vertexTL; _vertexArray[index++] = item.vertexTR; _vertexArray[index++] = item.vertexBL; _vertexArray[index++] = item.vertexBR; _freeBatchItemQueue.Enqueue(item); } // flush the remaining vertexArray data FlushVertexArray20(startIndex, index); _batchItemList.Clear(); }
public void DrawBatchGL20(SpriteSortMode sortMode) { // nothing to do if (_batchItemList.Count == 0) { return; } // sort the batch items switch (sortMode) { case SpriteSortMode.Texture: //_batchItemList.Sort( CompareTexture ); throw new NotSupportedException(); case SpriteSortMode.FrontToBack: //_batchItemList.Sort ( CompareDepth ); throw new NotSupportedException(); case SpriteSortMode.BackToFront: //_batchItemList.Sort ( CompareReverseDepth ); throw new NotSupportedException(); } GL20.EnableVertexAttribArray(attributePosition); GL20.EnableVertexAttribArray(attributeTexCoord); // make sure the vertexArray has enough space if (_batchItemList.Count * 4 > _index.Length) { ExpandIndexArray(_batchItemList.Count); } LinkVertexArray(); int size = VertexPosition2ColorTexture.GetSize(); GL20.VertexAttribPointer(attributePosition, 2, ALL20.Float, false, size, _vertexHandle.AddrOfPinnedObject()); GL20.VertexAttribPointer(attributeTexCoord, 2, ALL20.Float, false, size, (IntPtr)((uint)_vertexHandle.AddrOfPinnedObject() + (uint)(sizeof(float) * 2 + sizeof(uint)))); // setup the vertexArray array int startIndex = 0; int index = 0; int texID = -1; Color lastTint = new Color(0.0f, 0.0f, 0.0f, 0.0f); foreach (SpriteBatchItem item in _batchItemList) { //Tint Color Vector4 vtint = item.Tint.ToVector4(); //vtint /= 255; //GL20.VertexAttrib4(attributeTint, vtint.X, vtint.Y, vtint.Z, vtint.W); // if the texture changed, we need to flush and bind the new texture if (item.TextureID != texID || item.Tint != lastTint) { FlushVertexArrayGL20(startIndex, index); startIndex = index; texID = item.TextureID; lastTint = item.Tint; GL20.ActiveTexture(ALL20.Texture0); GL20.BindTexture(ALL20.Texture2D, texID); GL20.Uniform1(texID, 0); GL20.VertexAttrib4(attributeTint, vtint.X, vtint.Y, vtint.Z, vtint.W); } index += 4; } // flush the remaining vertexArray data FlushVertexArrayGL20(startIndex, index); _batchItemList.Clear(); _vertexArray.Clear(); }
public void InitWithData(IntPtr data, SurfaceFormat pixelFormat, int width, int height, Size size, ALL11 filter, ALL11 wrap) { if (GraphicsDevice.OpenGLESVersion == OpenTK.Graphics.GLContextVersion.Gles2_0) { if (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height)) { filter = ALL11.Linear; wrap = ALL11.ClampToEdge; } GL20.GenTextures(1, ref _name); GL20.BindTexture(ALL20.Texture2D, _name); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureMinFilter, (int)filter); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureMagFilter, (int)filter); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureWrapS, (int)wrap); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureWrapT, (int)wrap); switch (pixelFormat) { case SurfaceFormat.Color /*kTexture2DPixelFormat_RGBA8888*/: case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt3: //sz = 4; GL20.TexImage2D(ALL20.Texture2D, 0, (int)ALL20.Rgba, (int)width, (int)height, 0, ALL20.Rgba, ALL20.UnsignedByte, data); break; case SurfaceFormat.Bgra4444 /*kTexture2DPixelFormat_RGBA4444*/: //sz = 2; GL20.TexImage2D(ALL20.Texture2D, 0, (int)ALL20.Rgba, (int)width, (int)height, 0, ALL20.Rgba, ALL20.UnsignedShort4444, data); break; case SurfaceFormat.Bgra5551 /*kTexture2DPixelFormat_RGB5A1*/: //sz = 2; GL20.TexImage2D(ALL20.Texture2D, 0, (int)ALL20.Rgba, (int)width, (int)height, 0, ALL20.Rgba, ALL20.UnsignedShort5551, data); break; case SurfaceFormat.Alpha8 /*kTexture2DPixelFormat_A8*/: //sz = 1; GL20.TexImage2D(ALL20.Texture2D, 0, (int)ALL20.Alpha, (int)width, (int)height, 0, ALL20.Alpha, ALL20.UnsignedByte, data); break; default: throw new NotSupportedException("Texture format"); } } else { GL11.GenTextures(1, ref _name); GL11.BindTexture(ALL11.Texture2D, _name); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureMinFilter, (int)filter); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureMagFilter, (int)filter); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureWrapS, (int)ALL11.ClampToEdge); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureWrapT, (int)ALL11.ClampToEdge); switch (pixelFormat) { case SurfaceFormat.Color /*kTexture2DPixelFormat_RGBA8888*/: case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt3: GL11.TexImage2D(ALL11.Texture2D, 0, (int)ALL11.Rgba, (int)width, (int)height, 0, ALL11.Rgba, ALL11.UnsignedByte, data); break; case SurfaceFormat.Bgra4444 /*kTexture2DPixelFormat_RGBA4444*/: GL11.TexImage2D(ALL11.Texture2D, 0, (int)ALL11.Rgba, (int)width, (int)height, 0, ALL11.Rgba, ALL11.UnsignedShort4444, data); break; case SurfaceFormat.Bgra5551 /*kTexture2DPixelFormat_RGB5A1*/: GL11.TexImage2D(ALL11.Texture2D, 0, (int)ALL11.Rgba, (int)width, (int)height, 0, ALL11.Rgba, ALL11.UnsignedShort5551, data); break; case SurfaceFormat.Alpha8 /*kTexture2DPixelFormat_A8*/: GL11.TexImage2D(ALL11.Texture2D, 0, (int)ALL11.Alpha, (int)width, (int)height, 0, ALL11.Alpha, ALL11.UnsignedByte, data); break; default: throw new NotSupportedException("Texture format"); } } _size = size; _width = width; _height = height; _format = pixelFormat; _maxS = size.Width / (float)_width; _maxT = size.Height / (float)_height; }
public void InitWithBitmap(Bitmap imageSource, ALL11 filter, ALL11 wrap) { //TODO: Android.Opengl.GLUtils.GetInternalFormat() try { _format = SurfaceFormat.Color; if (imageSource.HasAlpha) { _format = SurfaceFormat.Color; } if (GraphicsDevice.OpenGLESVersion == OpenTK.Graphics.GLContextVersion.Gles2_0) { _width = imageSource.Width; _height = imageSource.Height; // There are rules for npot textures that we must abide by (wrap = ClampToEdge and filter = Nearest or Linear) if (!MathHelper.IsPowerOfTwo(_width) || !MathHelper.IsPowerOfTwo(_height)) { filter = ALL11.Linear; wrap = ALL11.ClampToEdge; } } else { //scale up bitmap to be power of 2 dimensions but dont exceed 1024x1024. //Note: may not have to do this with OpenGL 2+ _width = (int)Math.Pow(2, Math.Min(10, Math.Ceiling(Math.Log10(imageSource.Width) / Math.Log10(2)))); _height = (int)Math.Pow(2, Math.Min(10, Math.Ceiling(Math.Log10(imageSource.Height) / Math.Log10(2)))); } _size.Width = _width; _size.Height = _height; if (GraphicsDevice.OpenGLESVersion == OpenTK.Graphics.GLContextVersion.Gles2_0) { GL20.GenTextures(1, ref _name); } else { GL11.GenTextures(1, ref _name); } if (_name == 0) { _originalBitmap = imageSource; _originalFilter = filter; _originalWrap = wrap; PrimaryThreadLoader.AddToList(this); _textureCreated = false; } else { _originalBitmap = null; _textureCreated = true; using ( Bitmap imagePadded = Bitmap.CreateBitmap(_width, _height, Bitmap.Config.Argb8888) ) { using (Canvas can = new Canvas(imagePadded)) { can.DrawARGB(0, 0, 0, 0); if (AndroidCompatibility.ScaleImageToPowerOf2) { can.DrawBitmap(imageSource, new Rect(0, 0, imageSource.Width, imageSource.Height), new Rect(0, 0, _width, _height), null); //Scale to texture } else { can.DrawBitmap(imageSource, 0, 0, null); } if (GraphicsDevice.OpenGLESVersion == OpenTK.Graphics.GLContextVersion.Gles2_0) { GL20.BindTexture(ALL20.Texture2D, _name); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureMinFilter, (int)filter); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureMagFilter, (int)filter); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureWrapS, (int)wrap); GL20.TexParameter(ALL20.Texture2D, ALL20.TextureWrapT, (int)wrap); Android.Opengl.GLUtils.TexImage2D((int)ALL20.Texture2D, 0, imagePadded, 0); // error checking //int errAndroidGL = Android.Opengl.GLES20.GlGetError(); //ALL20 errGenericGL = GL20.GetError(); //if (errAndroidGL != Android.Opengl.GLES20.GlNoError || errGenericGL != ALL20.NoError) // Console.WriteLine(string.Format("OpenGL ES 2.0:\n\tAndroid error: {0,10:X}\n\tGeneric error: {1, 10:X}", errAndroidGL, errGenericGL)); } else { GL11.BindTexture(ALL11.Texture2D, _name); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureMinFilter, (int)filter); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureMagFilter, (int)filter); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureWrapS, (int)wrap); GL11.TexParameter(ALL11.Texture2D, ALL11.TextureWrapT, (int)wrap); GL11.TexParameter(ALL11.Texture2D, ALL11.GenerateMipmap, 1); Android.Opengl.GLUtils.TexImage2D((int)ALL11.Texture2D, 0, imagePadded, 0); } } } } } finally { if (_originalBitmap != imageSource) { // free bitmap imageSource.Dispose(); } } _maxS = _size.Width / (float)_width; _maxT = _size.Height / (float)_height; }
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; }
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]); } } }
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); }
protected override void Upload(PixelBox data, BasicBox dest) { GL.BindTexture(this.target, this.textureID); GLES2Config.GlCheckError(this); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != format || !data.IsConsecutive) { var glFormat = GLES2PixelUtil.GetClosestGLInternalFormat(format); //Data must be consecutive and at beginning of buffer as PixelStore is not allowed //for compressed formats if (dest.Left == 0 && dest.Top == 0) { GL.CompressedTexImage2D(this.faceTarget, this.level, glFormat, dest.Width, dest.Height, 0, data.ConsecutiveSize, data.Data.Pin()); GLES2Config.GlCheckError(this); } else { GL.CompressedTexSubImage2D(this.faceTarget, this.level, dest.Left, dest.Top, dest.Width, dest.Height, glFormat, data.ConsecutiveSize, data.Data.Pin()); GLES2Config.GlCheckError(this); } } } else if (this.softwareMipmap) { if (data.Width != data.RowPitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if (data.Height * data.Width != data.SlicePitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } GL.PixelStore(All.UnpackAlignment, 1); GLES2Config.GlCheckError(this); this.BuildMipmaps(data); } else { if (data.Width != data.RowPitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if (data.Height * data.Width != data.SlicePitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if ((data.Width * PixelUtil.GetNumElemBytes(data.Format) & 3) != 0) { //Standard alignment of 4 is not right GL.PixelStore(All.UnpackAlignment, 1); GLES2Config.GlCheckError(this); } var dataPtr = data.Data.Pin(); GL.TexImage2D(this.faceTarget, this.level, (int)GLES2PixelUtil.GetClosestGLInternalFormat(data.Format), data.Width, data.Height, 0, GLES2PixelUtil.GetGLOriginFormat(data.Format), GLES2PixelUtil.GetGLOriginDataType(data.Format), dataPtr); //GL.TexSubImage2D( this.faceTarget, this.level, dest.Left, dest.Top, dest.Width, dest.Height, GLES2PixelUtil.GetGLOriginFormat( data.Format ), GLES2PixelUtil.GetGLOriginDataType( data.Format ), dataPtr ); data.Data.UnPin(); GLES2Config.GlCheckError(this); } GL.PixelStore(All.UnpackAlignment, 4); GLES2Config.GlCheckError(this); }