Example #1
0
        private void PlatformSetData <T>(int level, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct
        {
            int x, y, w, h;

            if (rect.HasValue)
            {
                x = rect.Value.X;
                y = rect.Value.Y;
                w = rect.Value.Width;
                h = rect.Value.Height;
            }
            else
            {
                x = 0;
                y = 0;
                w = Math.Max(width >> level, 1);
                h = Math.Max(height >> level, 1);

                // For DXT textures the width and height of each level is a multiple of 4.
                // OpenGL only: The last two mip levels require the width and height to be
                // passed as 2x2 and 1x1, but there needs to be enough data passed to occupy
                // a 4x4 block.
                // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html
                if (_format == SurfaceFormat.Dxt1 ||
                    _format == SurfaceFormat.Dxt1a ||
                    _format == SurfaceFormat.Dxt3 ||
                    _format == SurfaceFormat.Dxt5)
                {
                    if (w > 4)
                    {
                        w = (w + 3) & ~3;
                    }
                    if (h > 4)
                    {
                        h = (h + 3) & ~3;
                    }
                }
            }
            _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h);
        }
Example #2
0
        public void SetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct 
        {
            if (data == null)
				throw new ArgumentNullException("data");

#if OPENGL
            Threading.BlockOnUIThread(() =>
            {
#endif
#if !PSM
                var elementSizeInByte = Marshal.SizeOf(typeof(T));
                var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                // Use try..finally to make sure dataHandle is freed in case of an error
                try
                {
                    var startBytes = startIndex * elementSizeInByte;
                    var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes);
#endif
                    int x, y, w, h;
                    if (rect.HasValue)
                    {
                        x = rect.Value.X;
                        y = rect.Value.Y;
                        w = rect.Value.Width;
                        h = rect.Value.Height;
                    }
                    else
                    {
                        x = 0;
                        y = 0;
                        w = Math.Max(width >> level, 1);
                        h = Math.Max(height >> level, 1);

                        // For DXT textures the width and height of each level is a multiple of 4.
                        // OpenGL only: The last two mip levels require the width and height to be 
                        // passed as 2x2 and 1x1, but there needs to be enough data passed to occupy 
                        // a 4x4 block. 
                        // Ref: http://www.mentby.com/Group/mac-opengl/issue-with-dxt-mipmapped-textures.html 
                        if (_format == SurfaceFormat.Dxt1 ||
                            _format == SurfaceFormat.Dxt1a ||
                            _format == SurfaceFormat.Dxt3 ||
                            _format == SurfaceFormat.Dxt5)
                        {
#if DIRECTX
                            w = (w + 3) & ~3;
                            h = (h + 3) & ~3;
#else
                            if (w > 4)
                                w = (w + 3) & ~3;
                            if (h > 4)
                                h = (h + 3) & ~3;
#endif
                        }
                    }

#if DIRECTX
                    var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0);

                    var region = new SharpDX.Direct3D11.ResourceRegion();
                    region.Top = y;
                    region.Front = 0;
                    region.Back = 1;
                    region.Bottom = y + h;
                    region.Left = x;
                    region.Right = x + w;

                    // TODO: We need to deal with threaded contexts here!
                    var d3dContext = GraphicsDevice._d3dContext;
                    lock (d3dContext)
						d3dContext.UpdateSubresource(box, GetTexture(), level, region);

#elif PSM
                    _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h);
#elif OPENGL

                    // Store the current bound texture.
                    var prevTexture = GraphicsExtensions.GetBoundTexture2D();

                    GenerateGLTextureIfRequired();

                    GL.BindTexture(TextureTarget.Texture2D, this.glTexture);
                    GraphicsExtensions.CheckGLError();
                    if (glFormat == (GLPixelFormat)All.CompressedTextureFormats)
                    {
                        if (rect.HasValue)
                        {
                            GL.CompressedTexSubImage2D(TextureTarget.Texture2D,
                                level, x, y, w, h,
#if GLES
                                glInternalFormat,
#else
                                glFormat,
#endif
                                data.Length - startBytes, dataPtr);
                            GraphicsExtensions.CheckGLError();
                        }
                        else
                        {
                            GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, data.Length - startBytes, dataPtr);
                            GraphicsExtensions.CheckGLError();
                        }
                    }
                    else
                    {
                        // Set pixel alignment to match texel size in bytes
                        GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.Size(this.Format));
                        if (rect.HasValue)
                        {
                            GL.TexSubImage2D(TextureTarget.Texture2D, level,
                                            x, y, w, h,
                                            glFormat, glType, dataPtr);
                            GraphicsExtensions.CheckGLError();
                        }
                        else
                        {
                            GL.TexImage2D(TextureTarget.Texture2D, level,
#if GLES
                                (int)glInternalFormat,
#else
                                glInternalFormat,
#endif
                                w, h, 0, glFormat, glType, dataPtr);
                            GraphicsExtensions.CheckGLError();
                        }
                        // Return to default pixel alignment
                        GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
                    }

#if !ANDROID
                    GL.Finish();
                    GraphicsExtensions.CheckGLError();
#endif
                    // Restore the bound texture.
                    GL.BindTexture(TextureTarget.Texture2D, prevTexture);
                    GraphicsExtensions.CheckGLError();

#endif // OPENGL

#if !PSM
                }
                finally
                {
                    dataHandle.Free();
                }
#endif

#if OPENGL
#if !ANDROID
                // Required to make sure that any texture uploads on a thread are completed
                // before the main thread tries to use the texture.
                GL.Finish();
#endif
            });
#endif
        }