Exemplo n.º 1
0
        protected override void BindSurfaceImpl(int attachment, RenderTexture target)
        {
            Contract.Requires(attachment < Config.MaxMultipleRenderTargets);

            // Get buffer and surface to bind to
            var buffer = (D3D9HardwarePixelBuffer)(target["BUFFER"]);

            Proclaim.NotNull(buffer);

            // Find first non null target
            int y;

            for (y = 0; y < Config.MaxMultipleRenderTargets && this._renderTargets[y] == null; ++y)
            {
                ;
            }

            if (y != Config.MaxMultipleRenderTargets)
            {
                // If there is another target bound, compare sizes
                if (this._renderTargets[y].Width != buffer.Width || this._renderTargets[y].Height != buffer.Height)
                {
                    throw new AxiomException("MultiRenderTarget surfaces are not the same size.");
                }

                if (!Root.Instance.RenderSystem.Capabilities.HasCapability(Capabilities.MRTDifferentBitDepths) &&
                    (PixelUtil.GetNumElemBits(this._renderTargets[y].Format) != PixelUtil.GetNumElemBits(buffer.Format)))
                {
                    throw new AxiomException("MultiRenderTarget surfaces are not of same bit depth and hardware requires it");
                }
            }

            this._renderTargets[attachment] = buffer;
            _checkAndUpdate();
        }
Exemplo n.º 2
0
 public void Rebind(XnaHardwarePixelBuffer buffer)
 {
     pixelBuffer = buffer;
     width       = pixelBuffer.Width;
     height      = pixelBuffer.Height;
     colorDepth  = PixelUtil.GetNumElemBits(buffer.Format);
 }
        public bool IsEquivalentFormatSupported(TextureType ttype, PixelFormat format, TextureUsage usage)
        {
            PixelFormat supportedFormat = GetNativeFormat(ttype, format, usage);

            // Assume that same or greater number of bits means quality not degraded
            return(PixelUtil.GetNumElemBits(supportedFormat) >= PixelUtil.GetNumElemBits(format));
        }
 public RenderTexture(HardwarePixelBuffer buffer, int zOffset)
 {
     pixelBuffer  = buffer;
     this.zOffset = zOffset;
     priority     = RenderTargetPriority.High;
     width        = buffer.Width;
     height       = buffer.Height;
     colorDepth   = PixelUtil.GetNumElemBits(buffer.Format);
 }
Exemplo n.º 5
0
        private FI.FIBITMAP _encode(Stream input, CodecData codecData)
        {
            var ret = new FI.FIBITMAP();

            ret.SetNull();
            var imgData = codecData as ImageData;

            if (imgData != null)
            {
                var data = new byte[(int)input.Length];
                input.Read(data, 0, data.Length);
                var dataPtr = BufferBase.Wrap(data);
                var src     = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, dataPtr);

                // The required format, which will adjust to the format
                // actually supported by FreeImage.
                var requiredFormat = imgData.format;

                // determine the settings
                var imageType         = FI.FREE_IMAGE_TYPE.FIT_UNKNOWN;
                var determiningFormat = imgData.format;

                switch (determiningFormat)
                {
                case PixelFormat.R5G6B5:
                case PixelFormat.B5G6R5:
                case PixelFormat.R8G8B8:
                case PixelFormat.B8G8R8:
                case PixelFormat.A8R8G8B8:
                case PixelFormat.X8R8G8B8:
                case PixelFormat.A8B8G8R8:
                case PixelFormat.X8B8G8R8:
                case PixelFormat.B8G8R8A8:
                case PixelFormat.R8G8B8A8:
                case PixelFormat.A4L4:
                case PixelFormat.BYTE_LA:
                case PixelFormat.R3G3B2:
                case PixelFormat.A4R4G4B4:
                case PixelFormat.A1R5G5B5:
                case PixelFormat.A2R10G10B10:
                case PixelFormat.A2B10G10R10:
                    // I'd like to be able to use r/g/b masks to get FreeImage to load the data
                    // in it's existing format, but that doesn't work, FreeImage needs to have
                    // data in RGB[A] (big endian) and BGR[A] (little endian), always.
                    if (PixelUtil.HasAlpha(determiningFormat))
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGRA;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGBA;
                        }
                    }
                    else
                    {
                        if (FI.FreeImageEngine.IsLittleEndian)
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }
                    }
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L8:
                case PixelFormat.A8:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
                    break;

                case PixelFormat.L16:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_UINT16;
                    break;

                case PixelFormat.SHORT_GR:
                    requiredFormat = PixelFormat.SHORT_RGB;
                    break;

                case PixelFormat.SHORT_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGB16;
                    break;

                case PixelFormat.SHORT_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBA16;
                    break;

                case PixelFormat.FLOAT16_R:
                    requiredFormat = PixelFormat.FLOAT32_R;
                    break;

                case PixelFormat.FLOAT32_R:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_FLOAT;
                    break;

                case PixelFormat.FLOAT16_GR:
                case PixelFormat.FLOAT16_RGB:
                case PixelFormat.FLOAT32_GR:
                    requiredFormat = PixelFormat.FLOAT32_RGB;
                    break;

                case PixelFormat.FLOAT32_RGB:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBF;
                    break;

                case PixelFormat.FLOAT16_RGBA:
                    requiredFormat = PixelFormat.FLOAT32_RGBA;
                    break;

                case PixelFormat.FLOAT32_RGBA:
                    imageType = FI.FREE_IMAGE_TYPE.FIT_RGBAF;
                    break;

                default:
                    throw new AxiomException("Not Supported image format :{0}", determiningFormat.ToString());
                } //end switch

                // Check support for this image type & bit depth
                if (!FI.FreeImage.FIFSupportsExportType((FI.FREE_IMAGE_FORMAT) this._freeImageType, imageType) ||
                    !FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType,
                                                       PixelUtil.GetNumElemBits(requiredFormat)))
                {
                    // Ok, need to allocate a fallback
                    // Only deal with RGBA . RGB for now
                    switch (requiredFormat)
                    {
                    case PixelFormat.BYTE_RGBA:
                        requiredFormat = PixelFormat.BYTE_RGB;
                        break;

                    case PixelFormat.BYTE_BGRA:
                        requiredFormat = PixelFormat.BYTE_BGR;
                        break;

                    default:
                        break;
                    }
                }

                var conversionRequired = false;
                input.Position = 0;
                var srcData = new byte[(int)input.Length];
                input.Read(srcData, 0, srcData.Length);
                var srcDataPtr = BufferBase.Wrap(srcData);

                // Check BPP
                var bpp = PixelUtil.GetNumElemBits(requiredFormat);
                if (!FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, bpp))
                {
                    if (bpp == 32 && PixelUtil.HasAlpha(imgData.format) &&
                        FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 24))
                    {
                        // drop to 24 bit (lose alpha)
                        if (FI.FreeImage.IsLittleEndian())
                        {
                            requiredFormat = PixelFormat.BYTE_BGR;
                        }
                        else
                        {
                            requiredFormat = PixelFormat.BYTE_RGB;
                        }

                        bpp = 24;
                    }
                    else if (bpp == 128 && PixelUtil.HasAlpha(imgData.format) &&
                             FI.FreeImage.FIFSupportsExportBPP((FI.FREE_IMAGE_FORMAT) this._freeImageType, 96))
                    {
                        // drop to 96-bit floating point
                        requiredFormat = PixelFormat.FLOAT32_RGB;
                    }
                }

                var convBox = new PixelBox(imgData.width, imgData.height, 1, requiredFormat);
                if (requiredFormat != imgData.format)
                {
                    conversionRequired = true;
                    // Allocate memory
                    var convData = new byte[convBox.ConsecutiveSize];
                    convBox.Data = BufferBase.Wrap(convData);
                    // perform conversion and reassign source
                    var newSrc = new PixelBox(imgData.width, imgData.height, 1, imgData.format, dataPtr);
                    PixelConverter.BulkPixelConversion(newSrc, convBox);
                    srcDataPtr = convBox.Data;
                }

                ret = FI.FreeImage.AllocateT(imageType, imgData.width, imgData.height, bpp);
                if (ret.IsNull)
                {
                    if (conversionRequired)
                    {
                        srcDataPtr.SafeDispose();
                        convBox = null;
                    }

                    throw new AxiomException("FreeImage.AllocateT failed - possibly out of memory. ");
                }

                if (requiredFormat == PixelFormat.L8 || requiredFormat == PixelFormat.A8)
                {
                    // Must explicitly tell FreeImage that this is greyscale by setting
                    // a "grey" palette (otherwise it will save as a normal RGB
                    // palettized image).
                    var tmp = FI.FreeImage.ConvertToGreyscale(ret);
                    FI.FreeImage.Unload(ret);
                    ret = tmp;
                }

                var dstPitch = (int)FI.FreeImage.GetPitch(ret);
                var srcPitch = imgData.width * PixelUtil.GetNumElemBytes(requiredFormat);

                // Copy data, invert scanlines and respect FreeImage pitch
                var pSrc = srcDataPtr;
                using (var pDest = BufferBase.Wrap(FI.FreeImage.GetBits(ret), imgData.height * srcPitch))
                {
                    var byteSrcData = pSrc;
                    var byteDstData = pDest;
                    for (var y = 0; y < imgData.height; ++y)
                    {
                        byteSrcData += (imgData.height - y - 1) * srcPitch;
                        Memory.Copy(pSrc, pDest, srcPitch);
                        byteDstData += dstPitch;
                    }
                }

                if (conversionRequired)
                {
                    // delete temporary conversion area
                    srcDataPtr.SafeDispose();
                    convBox = null;
                }
            }
            return(ret);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Detect allowed FBO formats
        /// </summary>
        private void _detectFBOFormats()
        {
            // Try all formats, and report which ones work as target
            int fb, tid;
            int old_drawbuffer, old_readbuffer;
            int target = Gl.GL_TEXTURE_2D;

            Gl.glGetIntegerv(Gl.GL_DRAW_BUFFER, out old_drawbuffer);
            Gl.glGetIntegerv(Gl.GL_READ_BUFFER, out old_readbuffer);

            for (int x = 0; x < (int)PixelFormat.Count; ++x)
            {
                this._props[x].Valid = false;

                // Fetch GL format token
                int fmt = GLPixelUtil.GetGLInternalFormat((PixelFormat)x);
                if (fmt == Gl.GL_NONE && x != 0)
                {
                    continue;
                }

                // No test for compressed formats
                if (PixelUtil.IsCompressed((PixelFormat)x))
                {
                    continue;
                }

                // Buggy ATI cards *crash* on non-RGB(A) formats
                int[] depths = PixelUtil.GetBitDepths((PixelFormat)x);
                if (fmt != Gl.GL_NONE && this._atiMode && (depths[0] == 0 || depths[1] == 0 || depths[2] == 0))
                {
                    continue;
                }

                // Buggy NVidia Drivers fail on 32Bit FP formats on Windows.
                if (PixelUtil.IsFloatingPoint((PixelFormat)x) && PlatformManager.IsWindowsOS && !this._atiMode)
                {
                    continue;
                }

                // Create and attach framebuffer
                Gl.glGenFramebuffersEXT(1, out fb);
                Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, fb);
                if (fmt != Gl.GL_NONE)
                {
                    // Create and attach texture
                    Gl.glGenTextures(1, out tid);
                    Gl.glBindTexture(target, tid);

                    // Set some default parameters so it won't fail on NVidia cards
                    Gl.glTexParameteri(target, Gl.GL_TEXTURE_MAX_LEVEL, 0);
                    Gl.glTexParameteri(target, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_NEAREST);
                    Gl.glTexParameteri(target, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_NEAREST);
                    Gl.glTexParameteri(target, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
                    Gl.glTexParameteri(target, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);

                    Gl.glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, IntPtr.Zero);
                    Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, target, tid, 0);
                }
                else
                {
                    // Draw to nowhere -- stencil/depth only
                    tid = 0;
                    Gl.glDrawBuffer(Gl.GL_NONE);
                    Gl.glReadBuffer(Gl.GL_NONE);
                }
                // Check status
                int status = Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT);

                // 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 == Gl.GL_NONE || status == Gl.GL_FRAMEBUFFER_COMPLETE_EXT)
                {
                    this._props[x].Valid = true;
                    var str = new StringBuilder();
                    str.AppendFormat("\tFBO {0} depth/stencil support: ", PixelUtil.GetFormatName((PixelFormat)x));

                    // For each depth/stencil formats
                    for (int depth = 0; depth < this._depthFormats.GetLength(0); ++depth)
                    {
                        if (this._depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT)
                        {
                            // General depth/stencil combination

                            for (int stencil = 0; stencil < this._stencilFormats.GetLength(0); ++stencil)
                            {
                                //LogManager.Instance.Write( "Trying {0} D{1}S{2} ", PixelUtil.GetFormatName( (PixelFormat)x ), _depthBits[ depth ], _stencilBits[ stencil ] );

                                if (_tryFormat(this._depthFormats[depth], this._stencilFormats[stencil]))
                                {
                                    /// Add mode to allowed modes
                                    str.AppendFormat("D{0}S{1} ", this._depthBits[depth], this._stencilBits[stencil]);
                                    FormatProperties.Mode mode;
                                    mode.Depth   = depth;
                                    mode.Stencil = stencil;
                                    this._props[x].Modes.Add(mode);
                                }
                            }
                        }
                        else
                        {
                            // Packed depth/stencil format
#if false
                            // Only query packed depth/stencil formats for 32-bit
                            // non-floating point formats (ie not R32!)
                            // Linux nVidia driver segfaults if you query others
                            if (!PlatformManager.IsWindowsOS &&
                                (PixelUtil.GetNumElemBits((PixelFormat)x) != 32 ||
                                 PixelUtil.IsFloatingPoint((PixelFormat)x)))
                            {
                                continue;
                            }
#endif
                            if (_tryPackedFormat(this._depthFormats[depth]))
                            {
                                /// Add mode to allowed modes
                                str.AppendFormat("Packed-D{0}S8 ", this._depthBits[depth]);
                                FormatProperties.Mode mode;
                                mode.Depth   = depth;
                                mode.Stencil = 0; // unuse
                                this._props[x].Modes.Add(mode);
                            }
                        }
                    }

                    LogManager.Instance.Write(str.ToString());
                }
                // Delete texture and framebuffer
                Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0);
                Gl.glDeleteFramebuffersEXT(1, ref fb);

                // Workaround for NVIDIA / Linux 169.21 driver problem
                // see http://www.ogre3d.org/phpBB2/viewtopic.php?t=38037&start=25
                Gl.glFinish();

                Gl.glDeleteTextures(1, ref tid);
            }

            // It seems a bug in nVidia driver: glBindFramebufferEXT should restore
            // draw and read buffers, but in some unclear circumstances it won't.
            Gl.glDrawBuffer(old_drawbuffer);
            Gl.glReadBuffer(old_readbuffer);

            string fmtstring = "";
            for (int x = 0; x < (int)PixelFormat.Count; ++x)
            {
                if (this._props[x].Valid)
                {
                    fmtstring += PixelUtil.GetFormatName((PixelFormat)x) + " ";
                }
            }
            LogManager.Instance.Write("[GL] : Valid FBO targets " + fmtstring);
        }
Exemplo n.º 7
0
        public virtual void LoadImages(Image[] images)
        {
            if (images.Length < 1)
            {
                throw new AxiomException("Cannot load empty vector of images");
            }

            // Set desired texture size and properties from images[0]
            this.srcWidth  = this.width = images[0].Width;
            this.srcHeight = this.height = images[0].Height;
            this.srcDepth  = this.depth = images[0].Depth;

            // Get source image format and adjust if required
            this.srcFormat = images[0].Format;
            if (this.treatLuminanceAsAlpha && this.srcFormat == PixelFormat.L8)
            {
                this.srcFormat = PixelFormat.A8;
            }

            if (this.desiredFormat != PixelFormat.Unknown)
            {
                // If have desired format, use it
                this.format = this.desiredFormat;
            }
            else
            {
                // Get the format according with desired bit depth
                this.format = PixelUtil.GetFormatForBitDepths(this.srcFormat, this.desiredIntegerBitDepth,
                                                              this.desiredFloatBitDepth);
            }

            // The custom mipmaps in the image have priority over everything
            var imageMips = images[0].NumMipMaps;

            if (imageMips > 0)
            {
                this.mipmapCount = this.requestedMipmapCount = imageMips;
                // Disable flag for auto mip generation
                this.usage &= ~TextureUsage.AutoMipMap;
            }

            // Create the texture
            CreateInternalResources();

            // Check if we're loading one image with multiple faces
            // or a vector of images representing the faces
            int  faces;
            bool multiImage;             // Load from multiple images?

            if (images.Length > 1)
            {
                faces      = images.Length;
                multiImage = true;
            }
            else
            {
                faces      = images[0].NumFaces;
                multiImage = false;
            }

            // Check wether number of faces in images exceeds number of faces
            // in this texture. If so, clamp it.
            if (faces > FaceCount)
            {
                faces = FaceCount;
            }

            // Say what we're doing
            if (TextureManager.Instance.Verbose)
            {
                var msg = new StringBuilder();
                msg.AppendFormat("Texture: {0}: Loading {1} faces( {2}, {3}x{4}x{5} ) with", _name, faces,
                                 PixelUtil.GetFormatName(images[0].Format), images[0].Width, images[0].Height,
                                 images[0].Depth);
                if (!(this.mipmapsHardwareGenerated && this.mipmapCount == 0))
                {
                    msg.AppendFormat(" {0}", this.mipmapCount);
                }

                if ((this.usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap)
                {
                    msg.AppendFormat("{0} generated mipmaps", this.mipmapsHardwareGenerated ? " hardware" : string.Empty);
                }
                else
                {
                    msg.Append(" custom mipmaps");
                }

                msg.AppendFormat(" from {0}.\n\t", multiImage ? "multiple Images" : "an Image");

                // Print data about first destination surface
                var buf = GetBuffer(0, 0);
                msg.AppendFormat(" Internal format is {0} , {1}x{2}x{3}.", PixelUtil.GetFormatName(buf.Format), buf.Width,
                                 buf.Height, buf.Depth);

                LogManager.Instance.Write(msg.ToString());
            }

            // Main loading loop
            // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
            for (var mip = 0; mip <= imageMips; ++mip)
            {
                for (var i = 0; i < faces; ++i)
                {
                    PixelBox src;
                    if (multiImage)
                    {
                        // Load from multiple images
                        src = images[i].GetPixelBox(0, mip);
                    }
                    else
                    {
                        // Load from faces of images[0]
                        src = images[0].GetPixelBox(i, mip);
                    }

                    // Sets to treated format in case is difference
                    src.Format = this.srcFormat;

                    if (this.gamma != 1.0f)
                    {
                        // Apply gamma correction
                        // Do not overwrite original image but do gamma correction in temporary buffer
                        var bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format);
                        var buff    = new byte[bufSize];
                        var buffer  = BufferBase.Wrap(buff);

                        var corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer);
                        PixelConverter.BulkPixelConversion(src, corrected);

                        Image.ApplyGamma(corrected.Data, this.gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format));

                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(corrected);
                    }
                    else
                    {
                        // Destination: entire texture. BlitFromMemory does
                        // the scaling to a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(src);
                    }
                }
            }

            // Update size (the final size, not including temp space)
            Size = FaceCount * PixelUtil.GetMemorySize(this.width, this.height, this.depth, this.format);
        }
Exemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="depth"></param>
        /// <param name="format"></param>
        private void SetSrcAttributes(int width, int height, int depth, PixelFormat format)
        {
            srcWidth  = width;
            srcHeight = height;
            srcBpp    = PixelUtil.GetNumElemBits(format);

            // say to the world what we are doing
            const string RenderTargetFormat = "[XNA] : Creating {0} RenderTarget, name : '{1}' with {2} mip map levels.";
            const string TextureFormat      = "[XNA] : Loading {0} Texture, image name : '{1}' with {2} mip map levels.";

            switch (TextureType)
            {
            case TextureType.OneD:
                if ((Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
                {
                    LogManager.Instance.Write(String.Format(RenderTargetFormat, TextureType.OneD, Name,
                                                            MipmapCount));
                }
                else
                {
                    LogManager.Instance.Write(String.Format(TextureFormat, TextureType.OneD, Name, MipmapCount));
                }
                break;

            case TextureType.TwoD:
                if ((Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
                {
                    LogManager.Instance.Write(String.Format(RenderTargetFormat, TextureType.TwoD, Name,
                                                            MipmapCount));
                }
                else
                {
                    LogManager.Instance.Write(String.Format(TextureFormat, TextureType.TwoD, Name, MipmapCount));
                }
                break;

            case TextureType.ThreeD:
                if ((Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
                {
                    LogManager.Instance.Write(String.Format(RenderTargetFormat, TextureType.ThreeD, Name,
                                                            MipmapCount));
                }
                else
                {
                    LogManager.Instance.Write(String.Format(TextureFormat, TextureType.ThreeD, Name, MipmapCount));
                }
                break;

            case TextureType.CubeMap:
                if ((Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
                {
                    LogManager.Instance.Write(String.Format(RenderTargetFormat, TextureType.CubeMap, Name,
                                                            MipmapCount));
                }
                else
                {
                    LogManager.Instance.Write(String.Format(TextureFormat, TextureType.CubeMap, Name, MipmapCount));
                }
                break;

            default:
                FreeInternalResources();
                throw new Exception("Unknown texture type");
            }
        }
Exemplo n.º 9
0
        protected virtual void LoadImages(List <Image> images)
        {
            Debug.Assert(images.Count >= 1);
            if (isLoaded)
            {
                log.InfoFormat("Unloading image: {0}", name);
                Unload();
            }
            srcWidth  = width = images[0].Width;
            srcHeight = height = images[0].Height;
            srcDepth  = depth = images[0].Depth;
            if (hasAlpha && images[0].Format == PixelFormat.L8)
            {
                format = PixelFormat.A8;
                srcBpp = 8;
            }
            else
            {
                this.Format = images[0].Format;
            }
            if (finalBpp == 16)
            {
                switch (format)
                {
                case PixelFormat.R8G8B8:
                case PixelFormat.X8R8G8B8:
                    format = PixelFormat.R5G6B5;
                    break;

                case PixelFormat.B8G8R8:
                case PixelFormat.X8B8G8R8:
                    format = PixelFormat.B5G6R5;
                    break;

                case PixelFormat.A8R8G8B8:
                case PixelFormat.R8G8B8A8:
                case PixelFormat.A8B8G8R8:
                case PixelFormat.B8G8R8A8:
                    format = PixelFormat.A4R4G4B4;
                    break;

                default:
                    // use the original format
                    break;
                }
            }

            // The custom mipmaps in the image have priority over everything
            int imageMips = images[0].NumMipMaps;

            if (imageMips > 0)
            {
                numMipmaps = imageMips;
                usage     &= ~TextureUsage.AutoMipMap;
            }

            // Create the texture
            CreateInternalResources();

            // Check if we're loading one image with multiple faces
            // or a vector of images representing the faces
            int  faces;
            bool multiImage;         // Load from multiple images?

            if (images.Count > 1)
            {
                faces      = images.Count;
                multiImage = true;
            }
            else
            {
                faces      = images[0].NumFaces;
                multiImage = false;
            }

            // Check wether number of faces in images exceeds number of faces
            // in this texture. If so, clamp it.
            if (faces > this.NumFaces)
            {
                faces = this.NumFaces;
            }

            // Say what we're doing
            log.InfoFormat("Texture: {0}: Loading {1} faces({2},{3}x{4}x{5})",
                           name, faces, PixelUtil.GetFormatName(images[0].Format),
                           images[0].Width, images[0].Height, images[0].Depth);
#if NOT // crazy ogre logging
            if (!(mMipmapsHardwareGenerated && mNumMipmaps == 0))
            {
                str << mNumMipmaps;
            }
            if (mUsage & TU_AUTOMIPMAP)
            {
                if (mMipmapsHardwareGenerated)
                {
                    str << " hardware";
                }

                str << " generated mipmaps";
            }
            else
            {
                str << " custom mipmaps";
            }
            if (multiImage)
            {
                str << " from multiple Images.";
            }
            else
            {
                str << " from Image.";
            }
            // Scoped
            {
                // Print data about first destination surface
                HardwarePixelBufferSharedPtr buf = getBuffer(0, 0);
                str << " Internal format is " << PixelUtil::getFormatName(buf->getFormat()) <<
                    "," << buf->getWidth() << "x" << buf->getHeight() << "x" << buf->getDepth() << ".";
            }
            LogManager::getSingleton().logMessage(
                LML_NORMAL, str.str());
#endif
            // Main loading loop
            // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
            for (int mip = 0; mip <= imageMips; ++mip)
            {
                for (int i = 0; i < faces; ++i)
                {
                    PixelBox src;
                    if (multiImage)
                    {
                        // Load from multiple images
                        src = images[i].GetPixelBox(0, mip);
                    }
                    else
                    {
                        // Load from faces of images[0]
                        src = images[0].GetPixelBox(i, mip);

                        if (hasAlpha && src.Format == PixelFormat.L8)
                        {
                            src.Format = PixelFormat.A8;
                        }
                    }

                    if (gamma != 1.0f)
                    {
                        // Apply gamma correction
                        // Do not overwrite original image but do gamma correction in temporary buffer
                        IntPtr buffer = Marshal.AllocHGlobal(PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format));
                        try {
                            PixelBox corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer);
                            PixelUtil.BulkPixelConversion(src, corrected);

                            Image.ApplyGamma(corrected.Data, gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format));

                            // Destination: entire texture. BlitFromMemory does the scaling to
                            // a power of two for us when needed
                            GetBuffer(i, mip).BlitFromMemory(corrected);
                        } finally {
                            Marshal.FreeHGlobal(buffer);
                        }
                    }
                    else
                    {
                        // Destination: entire texture. BlitFromMemory does the scaling to
                        // a power of two for us when needed
                        GetBuffer(i, mip).BlitFromMemory(src);
                    }
                }
            }
            // Update size (the final size, not including temp space)
            size = this.NumFaces * PixelUtil.GetMemorySize(width, height, depth, format);

            isLoaded = true;
        }