D3DTexture.cs :  » Game » RealmForge » Axiom » RenderSystems » DirectX9 » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Game » RealmForge 
RealmForge » Axiom » RenderSystems » DirectX9 » D3DTexture.cs
#region LGPL License
/*
Axiom Game Engine Library
Copyright (C) 2003  Axiom Project Team

The overall design, and a majority of the core engine and rendering code 
contained within this library is a derivative of the open source Object Oriented 
Graphics Engine OGRE, which can be found at http://ogre.sourceforge.net.  
Many thanks to the OGRE team for maintaining such a high quality project.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#endregion

using System;
using System.Diagnostics;
using System.IO;
using Axiom.Core;
using Axiom.Graphics;
using Axiom.Media;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3DMicrosoft.DirectX.Direct3D;

namespace Axiom.RenderSystems.DirectX9{
  /// <summary>
  /// Summary description for D3DTexture.
  /// </summary>
  public class D3DTexture : Axiom.Core.Texture {
    #region Fields

    /// <summary>
    ///     Direct3D device reference.
    /// </summary>
    private D3D.Device device;
    /// <summary>
    ///     Actual texture reference.
    /// </summary>
    private D3D.BaseTexture texture;
    /// <summary>
    ///     1D/2D normal texture.
    /// </summary>
    private D3D.Texture normTexture;
    /// <summary>
    ///     Cubic texture reference.
    /// </summary>
    private D3D.CubeTexture cubeTexture;
    /// <summary>
    ///     Temporary 1D/2D normal texture.
    /// </summary>
    private D3D.Texture tempNormTexture;
    /// <summary>
    ///     Temporary cubic texture reference.
    /// </summary>
    private D3D.CubeTexture tempCubeTexture;
    /// <summary>
    ///     3D volume texture.
    /// </summary>
    private D3D.VolumeTexture volumeTexture;
    /// <summary>
    ///     Render surface depth/stencil buffer. 
    /// </summary>
    private D3D.Surface depthBuffer;
    /// <summary>
    ///     Back buffer pixel format.
    /// </summary>
    private D3D.Format bbPixelFormat;
    /// <summary>
    ///     Direct3D device creation parameters.
    /// </summary>
    private D3D.DeviceCreationParameters devParms;
    /// <summary>
    ///     Direct3D device capability structure.
    /// </summary>
    private D3D.Caps devCaps;
    /// <summary>
    ///     Array to hold texture names used for loading cube textures.
    /// </summary>
    private string[] cubeFaceNames = new string[6];

    #endregion Fields
    
    public D3DTexture(string name, D3D.Device device, TextureUsage usage, TextureType type)
      : this(name, device, type, 0, 0, 0, PixelFormat.Unknown, usage) {}

    public D3DTexture(string name, D3D.Device device, TextureType type, int width, int height, int numMipMaps, Axiom.Media.PixelFormat format, TextureUsage usage) {
      Debug.Assert(device != null, "Cannot create a texture without a valid D3D Device.");

      this.name = name;
      this.usage = usage;
      this.textureType = type;

      // set the name of the cubemap faces
      if(this.TextureType == TextureType.CubeMap) {
        ConstructCubeFaceNames(name);
      }

      // get device caps
      devCaps = device.DeviceCaps;

      // save off the params used to create the Direct3D device
      this.device = device;
      devParms = device.CreationParameters;

      // get the pixel format of the back buffer
      using(D3D.Surface back = device.GetBackBuffer(0, 0, D3D.BackBufferType.Mono)) {
        bbPixelFormat = back.Description.Format;
      }

      SetSrcAttributes(width, height, 1, format);

      // if render target, create the texture up front
      if(usage == TextureUsage.RenderTarget) {
        CreateTexture();
        isLoaded = true;
      }
    }

    #region Properties

    /// <summary>
    ///    Gets the D3D Texture that is contained withing this Texture.
    /// </summary>
    public D3D.BaseTexture DXTexture {
      get { 
        return texture; 
      }
    }

    public D3D.Texture NormalTexture {
      get {
        return normTexture;
      }
    }

    public D3D.CubeTexture CubeTexture {
      get {
        return cubeTexture;
      }
    }

    public D3D.VolumeTexture VolumeTexture {
      get {
        return volumeTexture;
      }
    }

    public D3D.Surface DepthStencil {
      get {
        return depthBuffer;
      }
    }

    #endregion

    #region Methods

    public override void Load() {
      // unload if loaded already
            if (isLoaded) {
                Unload();
            }

            // log a quick message
            LogManager.Instance.Write("D3DTexture: Loading {0} with {1} mipmaps from an Image.", name, numMipMaps);

            // create a render texture if need be
      if(usage == TextureUsage.RenderTarget) {
        CreateTexture();
        isLoaded = true;
        return;
      }

      // create a regular texture
      switch(this.TextureType) {
        case TextureType.OneD:
        case TextureType.TwoD:
          LoadNormalTexture();
          break;

        case TextureType.ThreeD:
          LoadVolumeTexture();
          break;

        case TextureType.CubeMap:
          LoadCubeTexture();
          break;

        default:
          throw new Exception("Unsupported texture type!");
      }

      isLoaded = true;
    }

    public override void LoadImage(Image image) {
      // we need src image info
      this.SetSrcAttributes(image.Width, image.Height, 1, image.Format);
      // create a blank texture
      this.CreateNormalTexture();
      // set gamma prior to blitting
      Image.ApplyGamma(image.Data, this.gamma, image.Size, image.BitsPerPixel);
      this.BlitImageToNormalTexture(image);
      isLoaded = true;
    }

    /// <summary>
    /// 
    /// </summary>
    public override void Dispose() {
      base.Dispose ();

      if(texture != null)
        texture.Dispose();
    }

    /// <summary>
    ///    
    /// </summary>
    private void ConstructCubeFaceNames(string name) {
      string baseName, ext;
      string[] postfixes = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};

      int pos = name.LastIndexOf(".");

      baseName = name.Substring(0, pos);
      ext = name.Substring(pos);

      for(int i = 0; i < 6; i++) {
        cubeFaceNames[i] = baseName + postfixes[i] + ext;
      }
    }

    /// <summary>
    ///    
    /// </summary>
    private void LoadNormalTexture() {
      Debug.Assert(textureType == TextureType.OneD || textureType == TextureType.TwoD);

      Stream stream = TextureManager.Instance.FindResourceData(name);

      // use D3DX to load the image directly from the stream
      normTexture = TextureLoader.FromStream(device, stream);

      // store a ref for the base texture interface
      texture = normTexture;

      // set the image data attributes
      SurfaceDescription desc = normTexture.GetLevelDescription(0);
      SetSrcAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));
      SetFinalAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));

      isLoaded = true;
    }

    /// <summary>
    /// 
    /// </summary>
    private void LoadCubeTexture() {
      Debug.Assert(this.TextureType == TextureType.CubeMap, "this.TextureType == TextureType.CubeMap");

      if(name.EndsWith(".dds")) {
        Stream stream = TextureManager.Instance.FindResourceData(name);

        // load the cube texture from the image data stream directly
        cubeTexture = TextureLoader.FromCubeStream(device, stream);

        // store off a base reference
        texture = cubeTexture;

        // set src and dest attributes to the same, we can't know
        D3D.SurfaceDescription desc = cubeTexture.GetLevelDescription(0);
        SetSrcAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));
        SetFinalAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));
      }
      else {
        Image[] images = new Image[6];

        images[0] = Image.FromFile(cubeFaceNames[0]);
        SetSrcAttributes(images[0].Width, images[0].Height, 1, images[0].Format);

        // create the memory for the cube texture
        CreateCubeTexture();

        //                for(int i = 0; i < 6; i++) {
        //                    if(i > 0) {
        //                        images[i] = Image.FromFile(cubeFaceNames[i]);
        //                    }
        //
        //                    // apply gamma first
        //                    Image.ApplyGamma(images[i].Data, this.Gamma, images[i].Size, images[i].BitsPerPixel);
        //                }

        // load each face texture into the cube face of the cube texture
        BlitImagesToCubeTex();
      }

      isLoaded = true;
    }

    /// <summary>
    /// 
    /// </summary>
    private void LoadVolumeTexture() {
      Debug.Assert(this.TextureType == TextureType.ThreeD);

      Stream stream = TextureManager.Instance.FindResourceData(name);

      // load the cube texture from the image data stream directly
      volumeTexture = TextureLoader.FromVolumeStream(device, stream);

      // store off a base reference
      texture = volumeTexture;

      // set src and dest attributes to the same, we can't know
      D3D.VolumeDescription desc = volumeTexture.GetLevelDescription(0);
      SetSrcAttributes(desc.Width, desc.Height, desc.Depth, ConvertFormat(desc.Format));
      SetFinalAttributes(desc.Width, desc.Height, desc.Depth, ConvertFormat(desc.Format));
    }

    /// <summary>
    /// 
    /// </summary>
    private void CreateCubeTexture() {
      Debug.Assert(srcWidth > 0 && srcHeight > 0);

      // use current back buffer format for render textures, else use the one
      // defined by this texture format
      D3D.Format d3dPixelFormat = 
        (usage == TextureUsage.RenderTarget) ? bbPixelFormat : ChooseD3DFormat();

      // set the appropriate usage based on the usage of this texture
      D3D.Usage d3dUsage = 
        (usage == TextureUsage.RenderTarget) ? D3D.Usage.RenderTarget : 0;

      // how many mips to use?  make sure its at least one
      int numMips = (numMipMaps > 0) ? numMipMaps : 1;

      if(devCaps.TextureCaps.SupportsMipCubeMap) {
        if(this.CanAutoGenMipMaps(d3dUsage, ResourceType.CubeTexture, d3dPixelFormat)) {
          d3dUsage |= D3D.Usage.AutoGenerateMipMap;
          numMips = 0;
        }
      }
      else {
        // no mip map support for this kind of texture
        numMipMaps = 0;
        numMips = 1;
      }

      // HACK: Why does Managed D3D report R8G8B8 as an invalid format....
      if(d3dPixelFormat == D3D.Format.R8G8B8) {
        d3dPixelFormat = D3D.Format.A8R8G8B8;
      }

      // create the cube texture
      cubeTexture = new D3D.CubeTexture(
        device, 
        srcWidth, 
        numMips, 
        d3dUsage, 
        d3dPixelFormat, 
        (usage == TextureUsage.RenderTarget) ? Pool.Default : Pool.Managed);

      // set the final texture attributes
      D3D.SurfaceDescription desc = cubeTexture.GetLevelDescription(0);
      SetFinalAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));

      // store base reference to the texture
      texture = cubeTexture;

      if(usage == TextureUsage.RenderTarget) {
        CreateDepthStencil();
      }
    }

    /// <summary>
    /// 
    /// </summary>
    private void CreateDepthStencil() {
      // Get the format of the depth stencil surface of our main render target.
      D3D.Surface surface = device.DepthStencilSurface;
      D3D.SurfaceDescription desc = surface.Description;

      // Create a depth buffer for our render target, it must be of
      // the same format as other targets !!!
      depthBuffer = device.CreateDepthStencilSurface(
        srcWidth,
        srcHeight,
        // TODO: Verify this goes through, this is ridiculous
        (D3D.DepthFormat)desc.Format,
        desc.MultiSampleType,
        desc.MultiSampleQuality,
        false);
    }

    private void CreateNormalTexture() {
      Debug.Assert(srcWidth > 0 && srcHeight > 0);

      // use current back buffer format for render textures, else use the one
      // defined by this texture format
      D3D.Format d3dPixelFormat = 
        (usage == TextureUsage.RenderTarget) ? bbPixelFormat : ChooseD3DFormat();

      // set the appropriate usage based on the usage of this texture
      D3D.Usage d3dUsage = 
        (usage == TextureUsage.RenderTarget) ? D3D.Usage.RenderTarget : 0;

      // how many mips to use?  make sure its at least one
      int numMips = (numMipMaps > 0) ? numMipMaps : 1;

      D3D.TextureRequirements texRequire = new D3D.TextureRequirements();
      texRequire.Width = srcWidth;
      texRequire.Height = srcHeight;

      if(devCaps.TextureCaps.SupportsMipMap && numMipMaps > 0) {
        if(this.CanAutoGenMipMaps(d3dUsage, ResourceType.Textures, d3dPixelFormat)) {
          d3dUsage |= D3D.Usage.AutoGenerateMipMap;
          numMips = 0;
        }
        else {
          if(usage != TextureUsage.RenderTarget) {
            // check texture requirements
            texRequire.NumberMipLevels = numMips;
            texRequire.Format = d3dPixelFormat;
            TextureLoader.CheckTextureRequirements(device, d3dUsage, Pool.SystemMemory, out texRequire);
            numMips = texRequire.NumberMipLevels;
            d3dPixelFormat = texRequire.Format;

            // we must create a temp. texture in SYSTEM MEMORY if no auto gen. mip map is present
            tempNormTexture = new D3D.Texture(
              device,
              srcWidth,
              srcHeight,
              numMips,
              d3dUsage,
              d3dPixelFormat,
              Pool.SystemMemory);
          }
        }
      }
      else {
        // no mip map support for this kind of texture
        numMipMaps = 0;
        numMips = 1;
      }

      // check texture requirements
      texRequire.NumberMipLevels = numMips;
      texRequire.Format = d3dPixelFormat;
      TextureLoader.CheckTextureRequirements(device, d3dUsage, Pool.Default, out texRequire);
      numMips = texRequire.NumberMipLevels;
      d3dPixelFormat = texRequire.Format;

      // create the texture
      normTexture = new D3D.Texture(
        device, 
        srcWidth, 
        srcHeight,
        numMips, 
        d3dUsage, 
        d3dPixelFormat, 
        Pool.Default);

      // set the final texture attributes
      D3D.SurfaceDescription desc = normTexture.GetLevelDescription(0);
      SetFinalAttributes(desc.Width, desc.Height, 1, ConvertFormat(desc.Format));

      // store base reference to the texture
      texture = normTexture;

      if(usage == TextureUsage.RenderTarget) {
        CreateDepthStencil();
      }
    }

    private void BlitImageToNormalTexture(Image image) {
      D3D.Format srcFormat = ConvertFormat(image.Format);
      D3D.Format dstFormat = ChooseD3DFormat();

      // this surface will hold our temp conversion image
      // We need this in all cases because we can't lock 
      // the main texture surfaces in all cards
      // Also , this cannot be the temp texture because we'd like D3DX to resize it for us
      // with the D3DxLoadSurfaceFromSurface
      D3D.Surface srcSurface;
      srcSurface = device.CreateOffscreenPlainSurface(image.Width, image.Height, dstFormat, D3D.Pool.Scratch);

      // copy the buffer to our surface, 
      // copyMemoryToSurface will do color conversion and flipping
      CopyMemoryToSurface(image.Data, srcSurface);

      // Now we need to copy the source surface (where our image is) to the texture
      // This will be a temp texture for s/w filtering and the final one for h/w filtering
      // This will perform any size conversion (inc stretching)
      D3D.Surface dstSurface;

      if (tempNormTexture != null) {
        // s/w mipmaps, use temp texture
        dstSurface = tempNormTexture.GetSurfaceLevel(0);
      }
      else {
        // h/w mipmaps, use the final texture
        dstSurface = normTexture.GetSurfaceLevel(0);
      }

      // copy surfaces
      SurfaceLoader.FromSurface(dstSurface, srcSurface, D3D.Filter.Triangle | D3D.Filter.Dither, 0);

      if (tempNormTexture != null) {
        // Software filtering
        // Now update the texture & filter the results
        // we will use D3DX to create the mip map levels
        TextureLoader.FilterTexture(tempNormTexture, 0, D3D.Filter.Box);
        device.UpdateTexture(tempNormTexture, normTexture);
      }
      else {
        // Hardware mipmapping
        // use best filtering method supported by hardware
        texture.AutoGenerateFilterType = GetBestFilterMethod();
        normTexture.GenerateMipSubLevels();
      }

      dstSurface.Dispose();
    }

    private void CopyMemoryToSurface(byte[] buffer, D3D.Surface surface) {
      // Copy the image from the buffer to the temporary surface.
      // We have to do our own colour conversion here since we don't 
      // have a DC to do it for us
      // NOTE - only non-palettised surfaces supported for now
      D3D.SurfaceDescription desc;
      int pBuf8, pitch;
      uint data32, out32;
      int iRow, iCol;

      // NOTE - dimensions of surface may differ from buffer
      // dimensions (e.g. power of 2 or square adjustments)
      // Lock surface
      desc = surface.Description;
      uint aMask, rMask, gMask, bMask, rgbBitCount;

      GetColorMasks(desc.Format, out rMask, out gMask, out bMask, out aMask, out rgbBitCount);

      // lock our surface to acces raw memory
      GraphicsStream stream = surface.LockRectangle(D3D.LockFlags.NoSystemLock, out pitch);

      // loop through data and do conv.
      pBuf8 = 0;
      for( iRow = 0; iRow < srcHeight; iRow++ ) {
        stream.Position = iRow * pitch;
        for( iCol = 0; iCol < srcWidth; iCol++ ) {
          // Read RGBA values from buffer
          data32 = 0;
          if( srcBpp >= 24 ) {
            // Data in buffer is in RGB(A) format
            // Read into a 32-bit structure
            // Uses bytes for 24-bit compatibility
            // NOTE: buffer is big-endian
            data32 |= (uint)buffer[pBuf8++] << 24;
            data32 |= (uint)buffer[pBuf8++] << 16;
            data32 |= (uint)buffer[pBuf8++] << 8;
          }
          else if( srcBpp == 8 ) { // Greyscale, not palettised (palettised NOT supported)
            // Duplicate same greyscale value across R,G,B
            data32 |= (uint)buffer[pBuf8] << 24;
            data32 |= (uint)buffer[pBuf8] << 16;
            data32 |= (uint)buffer[pBuf8++] << 8;
          }
          // check for alpha
          if( hasAlpha ) {
            data32 |= buffer[pBuf8++];
          }
          else {
            data32 |= 0xFF;  // Set opaque
          }

          // Write RGBA values to surface
          // Data in surface can be in varying formats
          // Use bit concersion function
          // NOTE: we use a 32-bit value to manipulate
          // Will be reduced to size later

          // Red
          out32 = ConvertBitPattern( data32, 0xFF000000, rMask );
          // Green
          out32 |= ConvertBitPattern( data32, 0x00FF0000, gMask );
          // Blue
          out32 |= ConvertBitPattern( data32, 0x0000FF00, bMask );

          // Alpha
          if( aMask > 0 ) {
            out32 |= ConvertBitPattern( data32, 0x000000FF, aMask );
          }

          // Assign results to surface pixel
          // Write up to 4 bytes
          // Surfaces are little-endian (low byte first)
          if( rgbBitCount >= 8 ) {
            stream.WriteByte((byte)out32);
          }
          if( rgbBitCount >= 16 ) {
            stream.WriteByte((byte)(out32 >> 8));
          }
          if( rgbBitCount >= 24 ) {
            stream.WriteByte((byte)(out32 >> 16));
          }
          if( rgbBitCount >= 32 ) {
            stream.WriteByte((byte)(out32 >> 24));
          }
        } // for( iCol...
      } // for( iRow...
      // unlock the surface
      surface.UnlockRectangle();
    }

    private uint ConvertBitPattern(uint srcValue, uint srcBitMask, uint destBitMask) {
      // Mask off irrelevant source value bits (if any)
      srcValue = srcValue & srcBitMask;

      // Shift source down to bottom of DWORD
      int srcBitShift = GetBitShift(srcBitMask);
      srcValue >>= srcBitShift;

      // Get max value possible in source from srcMask
      uint srcMax = srcBitMask >> srcBitShift;

      // Get max avaiable in dest
      int destBitShift = GetBitShift(destBitMask);
      uint destMax = destBitMask >> destBitShift;

      // Scale source value into destination, and shift back
      uint destValue = (srcValue * destMax) / srcMax;
      return (destValue << destBitShift);
    }

    private int GetBitShift(uint mask) {
      if (mask == 0)
        return 0;

      int result = 0;
      while ((mask & 1) == 0) {
        ++result;
        mask >>= 1;
      }
      return result;
    }

    private void GetColorMasks(D3D.Format format, out uint red, out uint green, out uint blue, out uint alpha, out uint rgbBitCount) {
      // we choose the format of the D3D texture so check only for our pf types...
      switch (format) {
                case D3D.Format.X8R8G8B8:
                    red = 0x00FF0000; green = 0x0000FF00; blue = 0x000000FF; alpha = 0x00000000;
          rgbBitCount = 32;
          break;
        case D3D.Format.R8G8B8:
          red = 0x00FF0000; green = 0x0000FF00; blue = 0x000000FF; alpha = 0x00000000;
          rgbBitCount = 24;
          break;
        case D3D.Format.A8R8G8B8:
          red = 0x00FF0000; green = 0x0000FF00; blue = 0x000000FF; alpha = 0xFF000000;
          rgbBitCount = 32;
          break;
        case D3D.Format.X1R5G5B5:
          red = 0x00007C00; green = 0x000003E0; blue = 0x0000001F; alpha = 0x00000000;
          rgbBitCount = 16;
          break;
        case D3D.Format.R5G6B5:
          red = 0x0000F800; green = 0x000007E0; blue = 0x0000001F; alpha = 0x00000000;
          rgbBitCount = 16;
          break;
        case D3D.Format.A4R4G4B4:
          red = 0x00000F00; green = 0x000000F0; blue = 0x0000000F; alpha = 0x0000F000;
          rgbBitCount = 16;
          break;
        default:
          throw new AxiomException("Unknown D3D pixel format, this should not happen !!!");
      }
    }

    private D3D.TextureFilter GetBestFilterMethod() {
      // TODO : do it really :)
      return D3D.TextureFilter.Point;
    }

    /// <summary>
    ///     
    /// </summary>
    /// <param name="images"></param>
    /// <returns></returns>
    private void BlitImagesToCubeTex() {
      for(int i = 0; i < 6; i++) {
        // get a reference to the current cube surface for this iteration
        D3D.Surface dstSurface;

        // Now we need to copy the source surface (where our image is) to 
        // either the the temp. texture level 0 surface (for s/w mipmaps)
        // or the final texture (for h/w mipmaps)
        if(tempCubeTexture != null) {
          dstSurface = tempCubeTexture.GetCubeMapSurface((CubeMapFace)i, 0);
        }
        else {
          dstSurface = cubeTexture.GetCubeMapSurface((CubeMapFace)i, 0);
        }

        // copy the image data to a memory stream
        Stream stream = TextureManager.Instance.FindResourceData(cubeFaceNames[i]);

        // load the stream into the cubemap surface
        SurfaceLoader.FromStream(dstSurface, stream, Filter.Point, 0);

        dstSurface.Dispose();
      }

      // After doing all the faces, we generate mipmaps
      // For s/w mipmaps this involves an extra copying step
      // TODO: Find best filtering method for this hardware, currently hardcoded to Point
      if(tempCubeTexture != null) {
        TextureLoader.FilterTexture(tempCubeTexture, 0, Filter.Point);
        device.UpdateTexture(tempCubeTexture, cubeTexture);

        tempCubeTexture.Dispose();
      }
      else {
        cubeTexture.AutoGenerateFilterType = TextureFilter.Point;
        cubeTexture.GenerateMipSubLevels();
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="usage"></param>
    /// <param name="type"></param>
    /// <param name="format"></param>
    /// <returns></returns>
    private bool CanAutoGenMipMaps(D3D.Usage srcUsage, D3D.ResourceType srcType, D3D.Format srcFormat) {
      Debug.Assert(device != null);

      if(device.DeviceCaps.DriverCaps.CanAutoGenerateMipMap) {
        // make sure we can do it!
        return D3D.Manager.CheckDeviceFormat(
          devParms.AdapterOrdinal,
          devParms.DeviceType,
          bbPixelFormat,
          srcUsage | D3D.Usage.AutoGenerateMipMap,
          srcType,
          srcFormat);
      }

      return false;
    }

    public void CopyToTexture(Axiom.Core.Texture target) {
      // TODO: Check usage and format, need Usage property on Texture

      D3DTexture texture = (D3DTexture)target;

      if(target.TextureType == TextureType.TwoD) {
        using(D3D.Surface srcSurface = normTexture.GetSurfaceLevel(0),
              dstSurface = texture.NormalTexture.GetSurfaceLevel(0)) {

          System.Drawing.Rectangle srcRect = new System.Drawing.Rectangle(0, 0, this.Width, this.Height);
          System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(0, 0, target.Width, target.Height);
    
          // copy this texture surface to the target
          device.StretchRectangle(
            srcSurface, 
            srcRect, 
            dstSurface, 
            destRect, 
            TextureFilter.None);
        }
      }
      else {
        // TODO: Cube render targets
      }
    }

    /// <summary>
    /// 
    /// </summary>
    private void CreateTexture() {
      Debug.Assert(srcWidth > 0 && srcHeight > 0);

      switch(this.TextureType) {
        case TextureType.OneD:
        case TextureType.TwoD:
          CreateNormalTexture();
          break;

        case TextureType.CubeMap:
          CreateCubeTexture();
          break;

        default:
          throw new Exception("Unknown texture type!");
      }
    }

    private D3D.Format ChooseD3DFormat() {
      if(finalBpp > 16 && hasAlpha) {
        return D3D.Format.A8R8G8B8;
      }
      else if (finalBpp > 16 && !hasAlpha) {
        return D3D.Format.X8R8G8B8;
      }
      else if(finalBpp == 16 && hasAlpha) {
        return D3D.Format.A4R4G4B4;
      }
      else if(finalBpp == 16 && !hasAlpha) {
        return D3D.Format.R5G6B5;
      }
      else {
        throw new Exception("Unknown pixel format!");
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="format"></param>
    /// <returns></returns>
    public PixelFormat ConvertFormat(D3D.Format format) {
      switch(format) {
        case D3D.Format.A8:
          return PixelFormat.A8;
        case D3D.Format.A4L4:
          return PixelFormat.A4L4;
        case D3D.Format.A4R4G4B4:
          return PixelFormat.A4R4G4B4;
        case D3D.Format.A8R8G8B8:
          return PixelFormat.A8R8G8B8;
        case D3D.Format.A2R10G10B10:
          return PixelFormat.A2R10G10B10;
        case D3D.Format.L8:
          return PixelFormat.L8;
        case D3D.Format.X1R5G5B5:
        case D3D.Format.R5G6B5:
          return PixelFormat.R5G6B5;
        case D3D.Format.X8R8G8B8:
        case D3D.Format.R8G8B8:
          return PixelFormat.R8G8B8;
      }

      return PixelFormat.Unknown;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="format"></param>
    /// <returns></returns>
    public D3D.Format ConvertFormat(PixelFormat format) {
      switch(format) {
        case PixelFormat.L8:
          return D3D.Format.L8;
        case PixelFormat.A8:
          return D3D.Format.A8;
        case PixelFormat.B5G6R5:
        case PixelFormat.R5G6B5:
          return D3D.Format.R5G6B5;
        case PixelFormat.B4G4R4A4:
        case PixelFormat.A4R4G4B4:
          return D3D.Format.A4R4G4B4;
        case PixelFormat.B8G8R8:
        case PixelFormat.R8G8B8:
          return D3D.Format.R8G8B8;
        case PixelFormat.B8G8R8A8:
        case PixelFormat.A8R8G8B8:
          return D3D.Format.A8R8G8B8;
        case PixelFormat.L4A4:
        case PixelFormat.A4L4:
          return D3D.Format.A4L4;
        case PixelFormat.B10G10R10A2:
        case PixelFormat.A2R10G10B10:
          return D3D.Format.A2R10G10B10;
      }

      return D3D.Format.Unknown;
    }

    /// <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 = Image.GetNumElemBits(format);
      hasAlpha = Image.FormatHasAlpha(format);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <param name="depth"></param>
    /// <param name="format"></param>
    private void SetFinalAttributes(int width, int height, int depth, PixelFormat format) {
      // set target texture attributes
      this.height = height; 
      this.width = width; 
      this.depth = depth;
      this.format = format; 

      // Update size (the final size, not including temp space)
      // this is needed in Resource class
      int bytesPerPixel = finalBpp >> 3;
      if(!hasAlpha && finalBpp == 32) {
        bytesPerPixel--;
      }

      size = width * height * depth * bytesPerPixel * ((textureType == TextureType.CubeMap)? 6 : 1);
    }

    public override void Unload() {
      base.Unload();

      if(isLoaded) {
        if(texture != null) {
          texture.Dispose();
        }
        if(normTexture != null) {
          normTexture.Dispose();
        }
        if(cubeTexture != null) {
          cubeTexture.Dispose();
        }
        if(volumeTexture != null) {
          volumeTexture.Dispose();
        }
        if(depthBuffer != null) {
          depthBuffer.Dispose();
        }

        isLoaded = false;
      }
    }

    #endregion

  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.