Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PvrttTexLib.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Runtime.InteropServices;
6 using System.Security;
7 using System.IO;
8 using SiliconStudio.Core.Diagnostics;
9 using SiliconStudio.TextureConverter.PvrttWrapper;
10 using SiliconStudio.TextureConverter.Requests;
11 
12 namespace SiliconStudio.TextureConverter.TexLibraries
13 {
14 
15  /// <summary>
16  /// Class containing the needed native Data used by PVR Texture library
17  /// </summary>
18  internal class PvrTextureLibraryData : ITextureLibraryData
19  {
20  /// <summary>
21  /// A <see cref="PVRTexture" /> instance
22  /// </summary>
23  public PVRTexture Texture;
24 
25 
26  /// <summary>
27  /// The corresponding <see cref="PVRTextureHeader" /> to the <see cref="PVRTexture" /> above.
28  /// </summary>
29  public PVRTextureHeader Header;
30  }
31 
32  /// <summary>
33  /// Peforms requests from <see cref="TextureTool" /> using PVR Texture Tool.
34  /// </summary>
35  internal class PvrttTexLib : ITexLibrary
36  {
37  private static object lockObject = new object();
38  private static Logger Log = GlobalLogger.GetLogger("PvrttTexLib");
39 
40  /// <summary>
41  /// Initializes a new instance of the <see cref="PvrttTexLib"/> class.
42  /// </summary>
43  public PvrttTexLib() {}
44 
45  /// <summary>
46  /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. Nothing in this case
47  /// </summary>
48  public void Dispose() {}
49 
50 
51  public void Dispose(TexImage image)
52  {
53  if (!image.LibraryData.ContainsKey(this)) return;
54  PvrTextureLibraryData libraryData = (PvrTextureLibraryData)image.LibraryData[this];
55 
56  if (libraryData.Texture != null)
57  {
58  libraryData.Header = null;
59  libraryData.Texture.Dispose();
60  }
61  }
62 
63 
64  public bool SupportBGRAOrder()
65  {
66  return false;
67  }
68 
69  public bool CanHandleRequest(TexImage image, IRequest request)
70  {
71  switch (request.Type)
72  {
73  // Loading only file with a .pvr extension
74  case RequestType.Loading:
75  LoadingRequest loader = (LoadingRequest)request;
76  return loader.Mode == LoadingRequest.LoadingMode.FilePath && (Path.GetExtension(loader.FilePath).Equals(".pvr") || Path.GetExtension(loader.FilePath).Equals(".ktx"));
77 
78  case RequestType.Compressing:
79  CompressingRequest compress = (CompressingRequest)request;
80  return SupportFormat(compress.Format) && SupportFormat(image.Format);
81 
82  case RequestType.Export:
83  ExportRequest export = (ExportRequest)request;
84  return SupportFormat(image.Format) && (Path.GetExtension(export.FilePath).Equals(".pvr") || Path.GetExtension(export.FilePath).Equals(".ktx"));
85 
86  case RequestType.Decompressing:
87  return SupportFormat(image.Format);
88 
89  case RequestType.MipMapsGeneration:
90  return ((MipMapsGenerationRequest)request).Filter != Filter.MipMapGeneration.Box;
91 
92  case RequestType.Rescaling:
93  Filter.Rescaling filter = ((RescalingRequest)request).Filter;
94  return filter == Filter.Rescaling.Bicubic || filter == Filter.Rescaling.Bilinear || filter == Filter.Rescaling.Nearest;
95 
96  case RequestType.PreMultiplyAlpha:
97  case RequestType.SwitchingChannels:
98  case RequestType.Flipping:
99  case RequestType.NormalMapGeneration:
100  return true;
101 
102  default:
103  return false;
104  }
105  }
106 
107 
108  public void StartLibrary(TexImage image)
109  {
110  PvrTextureLibraryData libraryData = new PvrTextureLibraryData();
111 
112  int imageArraySize = image.Dimension == TexImage.TextureDimension.TextureCube ? image.ArraySize/6 : image.ArraySize;
113  int imageFaceCount = image.Dimension == TexImage.TextureDimension.TextureCube ? 6 : 1;
114 
115  // Creating native header corresponding to the TexImage instance
116  ulong format = RetrieveNativeFormat(image.Format);
117  EPVRTColourSpace colorSpace = RetrieveNativeColorSpace(image.Format);
118  EPVRTVariableType pixelType = RetrieveNativePixelType(image.Format);
119  libraryData.Header = new PVRTextureHeader(format, image.Height, image.Width, image.Depth, image.MipmapCount, imageArraySize, imageFaceCount, colorSpace, pixelType);
120 
121  int imageCount = 0;
122  int depth = image.Depth;
123  libraryData.Texture = new PVRTexture(libraryData.Header, IntPtr.Zero); // Initializing a new native texture, allocating memory.
124 
125  // Copying TexImage data into the native texture allocated memory
126  try
127  {
128  for (uint i = 0; i < imageFaceCount; ++i)
129  {
130  for (uint j = 0; j < imageArraySize; ++j)
131  {
132  for (uint k = 0; k < image.MipmapCount; ++k)
133  {
134  Core.Utilities.CopyMemory(libraryData.Texture.GetDataPtr(k, j, i), image.SubImageArray[imageCount].Data, image.SubImageArray[imageCount].DataSize * depth);
135  imageCount += depth;
136 
137  depth = depth > 1 ? depth >>= 1 : depth;
138  }
139  }
140  }
141  }
142  catch (AccessViolationException e)
143  {
144  libraryData.Texture.Dispose();
145  Log.Error("Failed to convert texture to PvrTexLib native data, check your texture settings. ", e);
146  throw new TextureToolsException("Failed to convert texture to PvrTexLib native data, check your texture settings. ", e);
147  }
148 
149  // Freeing previous image data
150  if (image.DisposingLibrary != null) image.DisposingLibrary.Dispose(image);
151 
152  image.LibraryData[this] = libraryData;
153 
154  image.DisposingLibrary = this;
155  }
156 
157 
158  public void EndLibrary(TexImage image)
159  {
160  // Retrieving native Data.
161  if (!image.LibraryData.ContainsKey(this)) return;
162  PvrTextureLibraryData libraryData = (PvrTextureLibraryData)image.LibraryData[this];
163 
164  // Updating current instance of TexImage with the native Data
165  UpdateImage(image, libraryData);
166 
167  /*
168  * in a 3D texture, the number of sub images will be different than for 2D : with 2D texture, you just have to multiply the mipmap levels with the array size.
169  * For 3D, when generating mip map, you generate mip maps for each slice of your texture, but the depth is decreasing by half (like the width and height) at
170  * each level. Then the number of sub images won't be mipmapCount * arraySize * depth, but arraySize * ( depth + depth/2 + depth/4 ... )
171  * ---- at each mipmap level ----
172  */
173  int imageCount, depth;
174  if (image.Dimension == TexImage.TextureDimension.Texture3D) // Counting the number of sub images according to the texture dimension
175  {
176  int subImagePerArrayElementCount = 0;
177  int curDepth = image.Depth;
178  for (int i = 0; i < image.MipmapCount; ++i)
179  {
180  subImagePerArrayElementCount += curDepth;
181  curDepth = curDepth > 1 ? curDepth >>= 1 : curDepth;
182  }
183 
184  imageCount = (int)(image.ArraySize * image.FaceCount * subImagePerArrayElementCount); // PvrTexLib added a "face" count above the texture array..
185  }
186  else
187  {
188  imageCount = (int)(image.ArraySize * image.FaceCount * image.MipmapCount);
189  }
190 
191  image.SubImageArray = new TexImage.SubImage[imageCount];
192  int ct = 0;
193  int rowPitch, slicePitch, height, width;
194 
195  for (uint i = 0; i < image.FaceCount; ++i) // Recreating the sub images
196  {
197  for (uint j = 0; j < image.ArraySize; ++j)
198  {
199  depth = image.Depth;
200  for (uint k = 0; k < image.MipmapCount; ++k)
201  {
202  width = (int)libraryData.Header.GetWidth(k);
203  height = (int)libraryData.Header.GetHeight(k);
204  Tools.ComputePitch(image.Format, width, height, out rowPitch, out slicePitch);
205 
206  for (int l = 0; l < depth; ++l)
207  {
208  image.SubImageArray[ct] = new TexImage.SubImage();
209  image.SubImageArray[ct].Width = width;
210  image.SubImageArray[ct].Height = height;
211  image.SubImageArray[ct].RowPitch = rowPitch;
212  image.SubImageArray[ct].SlicePitch = slicePitch;
213  image.SubImageArray[ct].DataSize = slicePitch;
214  image.SubImageArray[ct].Data = new IntPtr(libraryData.Texture.GetDataPtr(k, j, i).ToInt64() + l*slicePitch);
215  ++ct;
216  }
217  depth = depth > 1 ? depth >>= 1 : depth;
218  }
219  }
220  }
221 
222  // PVRTT uses a "face count" for CubeMap texture, the other librairies doesn't, it's just included in the arraySize
223  image.ArraySize = image.ArraySize * image.FaceCount;
224 
225  // This library is now the "owner" of the TexImage data, and must be used to handle the image data memory
226  image.DisposingLibrary = this;
227  }
228 
229 
230  public void Execute(TexImage image, IRequest request)
231  {
232  PvrTextureLibraryData libraryData = image.LibraryData.ContainsKey(this) ? (PvrTextureLibraryData)image.LibraryData[this] : null;
233 
234  switch (request.Type)
235  {
236  case RequestType.Loading:
237  Load(image, (LoadingRequest)request);
238  break;
239 
240  case RequestType.Compressing:
241  Compress(image, libraryData, (CompressingRequest)request);
242  break;
243 
244  case RequestType.Export:
245  Export(image, libraryData, (ExportRequest)request);
246  break;
247 
248  case RequestType.Decompressing:
249  Decompress(image, libraryData);
250  break;
251 
252  case RequestType.MipMapsGeneration:
253  GenerateMipMaps(image, libraryData, (MipMapsGenerationRequest)request);
254  break;
255 
256  case RequestType.SwitchingChannels:
257  SwitchChannels(image, libraryData, (SwitchingBRChannelsRequest)request);
258  break;
259 
260  case RequestType.Rescaling:
261  Rescale(image, libraryData, (RescalingRequest)request);
262  break;
263 
264  case RequestType.Flipping:
265  Flip(image, libraryData, (FlippingRequest)request);
266  break;
267 
268  case RequestType.NormalMapGeneration:
269  GenerateNormalMap(image, libraryData, (NormalMapGenerationRequest)request);
270  break;
271 
272  case RequestType.PreMultiplyAlpha:
273  PreMultiplyAlpha(image, libraryData);
274  break;
275 
276  default:
277  Log.Error("FITexLib (FreeImage) can't handle this request: " + request.Type);
278  throw new TextureToolsException("FITexLib (FreeImage) can't handle this request: " + request.Type);
279  }
280  }
281 
282 
283  /// <summary>
284  /// Loads the specified image.
285  /// </summary>
286  /// <param name="image">The image.</param>
287  /// <param name="request">The request.</param>
288  private void Load(TexImage image, LoadingRequest request)
289  {
290  Log.Info("Loading " + request.FilePath + " ...");
291 
292  PvrTextureLibraryData libraryData = new PvrTextureLibraryData();
293  image.LibraryData[this] = libraryData;
294 
295  libraryData.Texture = new PVRTexture(request.FilePath);
296  libraryData.Header = libraryData.Texture.GetHeader();
297 
298  image.Width = (int)libraryData.Header.GetWidth();
299  image.Height = (int)libraryData.Header.GetHeight();
300  image.Depth = (int)libraryData.Header.GetDepth();
301  image.Format = RetrieveFormatFromNativeData(libraryData.Header);
302 
303  int pitch, slice;
304  Tools.ComputePitch(image.Format, (int)image.Width, (int)image.Height, out pitch, out slice);
305  image.RowPitch = pitch;
306  image.SlicePitch = slice;
307 
308  image.DisposingLibrary = this;
309 
310  UpdateImage(image, libraryData);
311 
312  if (image.FaceCount > 1 && image.FaceCount % 6 == 0)
313  image.Dimension = TexImage.TextureDimension.TextureCube;
314  else if(image.Depth > 1)
315  image.Dimension = TexImage.TextureDimension.Texture3D;
316  else if (image.Height > 0)
317  image.Dimension = TexImage.TextureDimension.Texture2D;
318  else
319  image.Dimension = TexImage.TextureDimension.Texture1D;
320 
321  }
322 
323 
324  /// <summary>
325  /// Rescales the specified image.
326  /// </summary>
327  /// <param name="image">The image.</param>
328  /// <param name="libraryData">The library data.</param>
329  /// <param name="request">The request.</param>
330  private void Rescale(TexImage image, PvrTextureLibraryData libraryData, RescalingRequest request)
331  {
332  int width = request.ComputeWidth(image);
333  int height = request.ComputeHeight(image);
334 
335  Log.Info("Rescaling to " + width + "x" + height + " ...");
336 
337  EResizeMode filter;
338  switch(request.Filter)
339  {
340  case Filter.Rescaling.Bilinear:
341  filter = EResizeMode.eResizeLinear;
342  break;
343  case Filter.Rescaling.Bicubic:
344  filter = EResizeMode.eResizeCubic;
345  break;
346  case Filter.Rescaling.Nearest:
347  filter = EResizeMode.eResizeNearest;
348  break;
349  default:
350  filter = EResizeMode.eResizeCubic;
351  break;
352  }
353 
354  Utilities.Resize(libraryData.Texture, (uint)width, (uint)height, (uint)image.Depth, filter);
355  UpdateImage(image, libraryData);
356 
357  // Updating image data
358  image.Rescale(width, height);
359  }
360 
361 
362  /// <summary>
363  /// Exports the specified image.
364  /// </summary>
365  /// <param name="image">The image.</param>
366  /// <param name="libraryData">The library data.</param>
367  /// <param name="export">The export request.</param>
368  private void Export(TexImage image, PvrTextureLibraryData libraryData, ExportRequest request)
369  {
370  Log.Info("Exporting to " + request.FilePath + " ...");
371 
372  if (request.MinimumMipMapSize > 1) // if a mimimun mipmap size was requested
373  {
374  int newMipMapCount = image.MipmapCount;
375  for (int i = image.MipmapCount - 1; i > 0; --i) // looking for the mipmap level corresponding to the minimum size requeted.
376  {
377  if (libraryData.Header.GetWidth((uint)i) >= request.MinimumMipMapSize || libraryData.Header.GetHeight((uint)i) >= request.MinimumMipMapSize)
378  {
379  break;
380  }
381  --newMipMapCount;
382  }
383 
384  // Creating a new texture corresponding to the requested mipmap levels
385  PVRTextureHeader header = new PVRTextureHeader(RetrieveNativeFormat(image.Format), image.Height, image.Width, image.Depth, newMipMapCount, image.ArraySize, image.FaceCount);
386  PVRTexture texture = new PVRTexture(header, IntPtr.Zero);
387 
388  try
389  {
390  for (uint i = 0; i < image.FaceCount; ++i)
391  {
392  for (uint j = 0; j < image.ArraySize; ++j)
393  {
394  for (uint k = 0; k < newMipMapCount; ++k)
395  {
396  Core.Utilities.CopyMemory(texture.GetDataPtr(k, j, i), libraryData.Texture.GetDataPtr(k, j, i), (int)libraryData.Header.GetDataSize((int)k, false, false));
397  }
398  }
399  }
400  }
401  catch (AccessViolationException e)
402  {
403  texture.Dispose();
404  Log.Error("Failed to export texture with the mipmap minimum size request. ", e);
405  throw new TextureToolsException("Failed to export texture with the mipmap minimum size request. ", e);
406  }
407 
408  // Saving the texture into a file and deleting it
409  texture.Save(request.FilePath);
410  texture.Dispose();
411  }
412  else
413  {
414  libraryData.Texture.Save(request.FilePath);
415  }
416 
417  image.Save(request.FilePath);
418  }
419 
420 
421  /// <summary>
422  /// Switches the channels R and B.
423  /// </summary>
424  /// <param name="image">The image.</param>
425  /// <param name="libraryData">The library data.</param>
426  /// <param name="request">The request.</param>
427  /// <exception cref="TexLibraryException">Unsuported format for channel switching.</exception>
428  private void SwitchChannels(TexImage image, PvrTextureLibraryData libraryData, SwitchingBRChannelsRequest request)
429  {
430  Log.Info("Switching channels B and R ...");
431 
432  switch (image.Format)
433  {
434  case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm:
435  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm; break;
436  case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_Typeless:
437  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_Typeless; break;
438  case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm_SRgb:
439  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb; break;
440  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_Typeless:
441  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_Typeless; break;
442  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm:
443  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm; break;
444  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb:
445  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm_SRgb; break;
446  default:
447  Log.Error("Unsuported format for channel switching.");
448  throw new TextureToolsException("Unsuported format for channel switching.");
449  }
450 
451  PVRTexture textureTemp = new PVRTexture(libraryData.Header, libraryData.Texture.GetDataPtr());
452 
453  EChannelName e1 = EChannelName.eBlue;
454  EChannelName e2 = EChannelName.eRed;
455 
456  Utilities.CopyChannels(libraryData.Texture, textureTemp, 1, out e1, out e2);
457  Utilities.CopyChannels(libraryData.Texture, textureTemp, 1, out e2, out e1);
458 
459  textureTemp.Dispose();
460 
461  UpdateImage(image, libraryData);
462  }
463 
464 
465  /// <summary>
466  /// Compresses the specified image.
467  /// </summary>
468  /// <param name="image">The image.</param>
469  /// <param name="libraryData">The library data.</param>
470  /// <param name="compress">The compress.</param>
471  /// <exception cref="TexLibraryException">Compression failed</exception>
472  private void Compress(TexImage image, PvrTextureLibraryData libraryData, CompressingRequest compress)
473  {
474  Log.Info("Compressing to " + compress.Format + " ...");
475 
476  ulong format = RetrieveNativeFormat(compress.Format);
477  EPVRTColourSpace colorSpace = RetrieveNativeColorSpace(compress.Format);
478  EPVRTVariableType pixelType = RetrieveNativePixelType(compress.Format);
479 
480  lock (lockObject)
481  {
482  if (!Utilities.Transcode(libraryData.Texture, format, pixelType, colorSpace, (ECompressorQuality)compress.Quality, false))
483  {
484  Log.Error("Compression failed!");
485  throw new TextureToolsException("Compression failed!");
486  }
487  }
488 
489  image.Format = compress.Format;
490  int pitch, slice;
491  Tools.ComputePitch(image.Format, image.Width, image.Height, out pitch, out slice);
492  image.RowPitch = pitch;
493  image.SlicePitch = slice;
494 
495  UpdateImage(image, libraryData);
496  }
497 
498 
499  /// <summary>
500  /// Decompresses the specified image.
501  /// </summary>
502  /// <param name="image">The image.</param>
503  /// <param name="libraryData">The library data.</param>
504  /// <exception cref="TexLibraryException">Decompression failed!</exception>
505  public void Decompress(TexImage image, PvrTextureLibraryData libraryData)
506  {
507  Log.Info("Decompressing texture ...");
508 
509  if (!Utilities.Transcode(libraryData.Texture, PixelType.Standard8PixelType, libraryData.Header.GetChannelType(), libraryData.Header.GetColourSpace(), ECompressorQuality.ePVRTCNormal, true))
510  {
511  Log.Error("Decompression failed!");
512  throw new TextureToolsException("Decompression failed!");
513  }
514 
515  image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm;
516 
517  int pitch,slice;
518  Tools.ComputePitch(image.Format, image.Width, image.Height, out pitch, out slice);
519  image.RowPitch = pitch;
520  image.SlicePitch = slice;
521 
522  UpdateImage(image, libraryData);
523  }
524 
525 
526  /// <summary>
527  /// Generates the mip maps.
528  /// </summary>
529  /// <param name="image">The image.</param>
530  /// <param name="libraryData">The library data.</param>
531  /// <param name="request">The request.</param>
532  private void GenerateMipMaps(TexImage image, PvrTextureLibraryData libraryData, MipMapsGenerationRequest request)
533  {
534  Log.Info("Generating Mipmaps ... ");
535 
536  EResizeMode filter;
537  switch (request.Filter)
538  {
539  case Filter.MipMapGeneration.Linear:
540  filter = EResizeMode.eResizeLinear;
541  break;
542  case Filter.MipMapGeneration.Cubic:
543  filter = EResizeMode.eResizeCubic;
544  break;
545  case Filter.MipMapGeneration.Nearest:
546  filter = EResizeMode.eResizeNearest;
547  break;
548  default:
549  filter = EResizeMode.eResizeCubic;
550  break;
551  }
552 
553  libraryData.Texture.GenerateMIPMaps(filter);
554 
555  UpdateImage(image, libraryData);
556  }
557 
558 
559  /// <summary>
560  /// Flips the specified image vertically or horizontally.
561  /// </summary>
562  /// <param name="image">The image.</param>
563  /// <param name="libraryData">The library data.</param>
564  /// <param name="request">The request.</param>
565  /// <exception cref="TexLibraryException">Flipping failed.</exception>
566  private void Flip(TexImage image, PvrTextureLibraryData libraryData, FlippingRequest request)
567  {
568  Log.Info("Flipping texture : " + request.Flip + " ... ");
569 
570  switch(request.Flip)
571  {
572  case Orientation.Horizontal:
573  if (!Utilities.Flip(libraryData.Texture, EPVRTAxis.ePVRTAxisX))
574  {
575  Log.Error("Flipping failed.");
576  throw new TextureToolsException("Flipping failed.");
577  }
578  break;
579  case Orientation.Vertical:
580  if (!Utilities.Flip(libraryData.Texture, EPVRTAxis.ePVRTAxisY))
581  {
582  Log.Error("Flipping failed.");
583  throw new TextureToolsException("Flipping failed.");
584  }
585  break;
586  }
587 
588  image.Flip(request.Flip);
589 
590  UpdateImage(image, libraryData);
591  }
592 
593  /// <summary>
594  /// Generates the normal map.
595  /// </summary>
596  /// <param name="image">The image.</param>
597  /// <param name="libraryData">The library data.</param>
598  /// <param name="request">The request.</param>
599  /// <exception cref="TexLibraryException">Failed to generate normal map.</exception>
600  public void GenerateNormalMap(TexImage image, PvrTextureLibraryData libraryData, NormalMapGenerationRequest request)
601  {
602  Log.Info("Generating Normal Map ... ");
603 
604  // Creating new TexImage with the normal map data.
605  request.NormalMap = new TexImage();
606  PvrTextureLibraryData normalMapLibraryData = new PvrTextureLibraryData();
607  request.NormalMap.LibraryData[this] = normalMapLibraryData;
608 
609  normalMapLibraryData.Texture = new PVRTexture(libraryData.Header, libraryData.Texture.GetDataPtr());
610  request.NormalMap.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm;
611  request.NormalMap.CurrentLibrary = this;
612  request.NormalMap.DisposingLibrary = this;
613 
614  if (!Utilities.GenerateNormalMap(normalMapLibraryData.Texture, request.Amplitude, "xyzh"))
615  {
616  Log.Error("Failed to generate normal map.");
617  throw new TextureToolsException("Failed to generate normal map.");
618  }
619 
620  UpdateImage(request.NormalMap, normalMapLibraryData);
621  EndLibrary(request.NormalMap);
622  request.NormalMap.DisposingLibrary = this;
623  }
624 
625 
626  /// <summary>
627  /// Premultiplies the alpha on the specified texture.
628  /// </summary>
629  /// <param name="image">The image.</param>
630  /// <param name="libraryData">The library data.</param>
631  /// <exception cref="TexLibraryException">Failed to premultiply the alpha.</exception>
632  public void PreMultiplyAlpha(TexImage image, PvrTextureLibraryData libraryData)
633  {
634  Log.Info("Premultiplying alpha ... ");
635 
636  if (!Utilities.PreMultipliedAlpha(libraryData.Texture))
637  {
638  Log.Info("Failed to premultiply the alpha.");
639  throw new TextureToolsException("Failed to premultiply the alpha.");
640  }
641  }
642 
643 
644  /// <summary>
645  /// Updates the image basic information with the native data.
646  /// </summary>
647  /// <param name="image">The image.</param>
648  /// <param name="libraryData">The library data.</param>
649  private void UpdateImage(TexImage image, PvrTextureLibraryData libraryData)
650  {
651  image.Data = libraryData.Texture.GetDataPtr();
652  libraryData.Header = libraryData.Texture.GetHeader();
653  image.DataSize = (int)libraryData.Header.GetDataSize();
654  image.MipmapCount = (int)libraryData.Header.GetNumMIPLevels();
655  image.ArraySize = (int)libraryData.Header.GetNumArrayMembers();
656  image.FaceCount = (int)libraryData.Header.GetNumFaces();
657  }
658 
659 
660  /// <summary>
661  /// Determines whether the specified compression format is supported by this library
662  /// </summary>
663  /// <param name="format">The format.</param>
664  /// <returns>
665  /// <c>true</c> if the formats is supported by this library; otherwise, <c>false</c>.
666  /// </returns>
667  private bool SupportFormat(SiliconStudio.Paradox.Graphics.PixelFormat format)
668  {
669  switch (format)
670  {
671  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_Float:
672  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_Float:
673  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_UInt:
674  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_UInt:
675  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_SInt:
676  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_SInt:
677  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UNorm:
678  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UInt:
679  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SNorm:
680  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SInt:
681  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb:
682  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm:
683  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UInt:
684  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SNorm:
685  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SInt:
686  case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm_SRgb:
687  case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm:
688 
689  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_2bpp_RGB:
690  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_2bpp_RGBA:
691  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_4bpp_RGB:
692  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_4bpp_RGBA:
693  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_II_2bpp:
694  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_II_4bpp:
695  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC1:
696  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGB:
697  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGBA:
698  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGB_A1:
699  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_R11_Unsigned:
700  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_R11_Signed:
701  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_RG11_Unsigned:
702  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_RG11_Signed:
703  return true;
704  default:
705  return false;
706  }
707  }
708 
709  /// <summary>
710  /// Retrieves the native format from the PixelFormat.
711  /// </summary>
712  /// <param name="format">The format.</param>
713  /// <returns></returns>
714  /// <exception cref="TexLibraryException">UnHandled compression format by PowerVC Texture Tool.</exception>
715  private UInt64 RetrieveNativeFormat(SiliconStudio.Paradox.Graphics.PixelFormat format)
716  {
717  switch (format)
718  {
719  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_2bpp_RGB:
720  return 0;
721  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_2bpp_RGBA:
722  return 1;
723  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_4bpp_RGB:
724  return 2;
725  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_4bpp_RGBA:
726  return 3;
727  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_II_2bpp:
728  return 4;
729  case SiliconStudio.Paradox.Graphics.PixelFormat.PVRTC_II_4bpp:
730  return 5;
731  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC1:
732  return 6;
733  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGB:
734  return 22;
735  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGBA:
736  return 23;
737  case SiliconStudio.Paradox.Graphics.PixelFormat.ETC2_RGB_A1:
738  return 24;
739  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_R11_Unsigned:
740  return 25;
741  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_R11_Signed:
742  return 26;
743  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_RG11_Unsigned:
744  return 27;
745  case SiliconStudio.Paradox.Graphics.PixelFormat.EAC_RG11_Signed:
746  return 28;
747  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_Float:
748  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_Float:
749  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_UInt:
750  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_UInt:
751  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_SInt:
752  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_SInt:
753  return Utilities.ConvertPixelType(PixelType.Standard32PixelType);
754  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UNorm:
755  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UInt:
756  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SNorm:
757  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SInt:
758  return Utilities.ConvertPixelType(PixelType.Standard16PixelType);
759  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb:
760  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm:
761  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UInt:
762  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SNorm:
763  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SInt:
764  return Utilities.ConvertPixelType(PixelType.Standard8PixelType);
765  default:
766  Log.Error("UnHandled compression format by PowerVC Texture Tool.");
767  throw new TextureToolsException("UnHandled compression format by PowerVC Texture Tool.");
768  }
769  }
770 
771 
772  private EPVRTVariableType RetrieveNativePixelType(SiliconStudio.Paradox.Graphics.PixelFormat format)
773  {
774  switch (format)
775  {
776  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_Float:
777  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_Float:
778  return EPVRTVariableType.ePVRTVarTypeFloat;
779  //case Paradox.Framework.Graphics.PixelFormat.R16G16B16A16_Float:
780 
781  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_UInt:
782  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_UInt:
783  return EPVRTVariableType.ePVRTVarTypeUnsignedInteger;
784  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_SInt:
785  case SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32_SInt:
786  return EPVRTVariableType.ePVRTVarTypeSignedInteger;
787 
788  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UNorm:
789  return EPVRTVariableType.ePVRTVarTypeUnsignedShortNorm;
790  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UInt:
791  return EPVRTVariableType.ePVRTVarTypeUnsignedShort;
792  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SNorm:
793  return EPVRTVariableType.ePVRTVarTypeSignedShortNorm;
794  case SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SInt:
795  return EPVRTVariableType.ePVRTVarTypeSignedShort;
796 
797 
798  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb:
799  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm:
800  return EPVRTVariableType.ePVRTVarTypeUnsignedByteNorm;
801  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UInt:
802  return EPVRTVariableType.ePVRTVarTypeUnsignedByte;
803  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SNorm:
804  return EPVRTVariableType.ePVRTVarTypeSignedByteNorm;
805  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SInt:
806  return EPVRTVariableType.ePVRTVarTypeSignedByte;
807 
808  default:
809  return EPVRTVariableType.ePVRTVarTypeUnsignedByteNorm;
810  }
811  }
812 
813 
814  private SiliconStudio.Paradox.Graphics.PixelFormat RetrieveFormatFromNativeData(PVRTextureHeader header)
815  {
816  SiliconStudio.Paradox.Graphics.PixelFormat format = header.GetFormat();
817  if (format == SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_Float)
818  {
819  switch (header.GetChannelType())
820  {
821  case EPVRTVariableType.ePVRTVarTypeFloat:
822  return SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_Float;
823  case EPVRTVariableType.ePVRTVarTypeUnsignedInteger:
824  return SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_UInt;
825  case EPVRTVariableType.ePVRTVarTypeSignedInteger:
826  return SiliconStudio.Paradox.Graphics.PixelFormat.R32G32B32A32_SInt;
827  }
828  }
829  else if(format == SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UNorm)
830  {
831  switch (header.GetChannelType())
832  {
833  case EPVRTVariableType.ePVRTVarTypeUnsignedShortNorm:
834  return SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UNorm;
835  case EPVRTVariableType.ePVRTVarTypeUnsignedShort:
836  return SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_UInt;
837  case EPVRTVariableType.ePVRTVarTypeSignedShortNorm:
838  return SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SNorm;
839  case EPVRTVariableType.ePVRTVarTypeSignedShort:
840  return SiliconStudio.Paradox.Graphics.PixelFormat.R16G16B16A16_SInt;
841  }
842  }
843  else if(format == SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm)
844  {
845  switch (header.GetChannelType())
846  {
847  case EPVRTVariableType.ePVRTVarTypeUnsignedByteNorm:
848  {
849  if (header.GetColourSpace() == EPVRTColourSpace.ePVRTCSpacelRGB)
850  return SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm;
851  else
852  return SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb;
853  }
854  case EPVRTVariableType.ePVRTVarTypeUnsignedByte:
855  return SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UInt;
856  case EPVRTVariableType.ePVRTVarTypeSignedByteNorm:
857  return SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SNorm;
858  case EPVRTVariableType.ePVRTVarTypeSignedByte:
859  return SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_SInt;
860  }
861  }
862 
863  return format;
864  }
865 
866  private EPVRTColourSpace RetrieveNativeColorSpace(SiliconStudio.Paradox.Graphics.PixelFormat format)
867  {
868  switch (format)
869  {
870  case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb:
871  return EPVRTColourSpace.ePVRTCSpaceSRgb;
872  default:
873  return EPVRTColourSpace.ePVRTCSpacelRGB;
874  }
875  }
876  }
877 }
HRESULT GenerateMipMaps(_In_ const Image &baseImage, _In_ DWORD filter, _In_ size_t levels, _Inout_ ScratchImage &mipChain, _In_ bool allow1D=false)
Base implementation for ILogger.
Definition: Logger.cs:10
switch(inFormat)
SiliconStudio.Core.Utilities Utilities
Definition: Texture.cs:29
Same as Deferred mode, except sprites are sorted by texture prior to drawing. This can improve perfor...
HRESULT Decompress(_In_ const Image &cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage &image)
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
Output message to log right away.
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
HRESULT Compress(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage &cImage)