Skip to content
This repository

DXT and PVRTC Mipmap Generation #1645

Merged
merged 4 commits into from about 1 year ago

4 participants

Ray Batts MonoGame Build Bot Tom Spilman Steve 'Sly' Williams
Ray Batts

Note that this won't generate mipmaps for uncompressed textures. That'll come as soon as I get a little time to get to it.

MonoGame Build Bot
Collaborator
mgbot commented April 11, 2013

Can one of the admins verify this patch?

MonoGame Build Bot
Collaborator
mgbot commented April 11, 2013

Can one of the admins verify this patch?

Tom Spilman
Collaborator

@mgbot test

Tom Spilman
Collaborator

Note this is new MonoGame Content Pipeline stuff... it doesn't affect the old processors or runtime.

MonoGame Build Bot
Collaborator
mgbot commented April 11, 2013

Build results will soon be (or already are) available at: http://build.monogame.net/job/PullRequestTester/105/

Steve 'Sly' Williams KonajuGames merged commit a3b0db9 into from April 15, 2013
Steve 'Sly' Williams KonajuGames closed this April 15, 2013
Tom Spilman tomspilman deleted the branch January 20, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
64  MonoGame.Framework.Content.Pipeline/Graphics/GraphicsUtil.cs
@@ -54,7 +54,12 @@ protected bool writeData(IntPtr data, int length)
54 54
             Marshal.Copy(data, dataBuffer, 0, length);
55 55
 
56 56
             var texContent = new DXTBitmapContent(_format == Format.DXT1 ? 8 : 16, _levelWidth, _levelHeight);
57  
-            _content.Faces[0][_currentMipLevel] = texContent;
  57
+
  58
+            if (_content.Faces[0].Count == _currentMipLevel)
  59
+                _content.Faces[0].Add(texContent);
  60
+            else
  61
+                _content.Faces[0][_currentMipLevel] = texContent;
  62
+
58 63
             _content.Faces[0][_currentMipLevel].SetPixelData(dataBuffer);
59 64
 
60 65
             return true;
@@ -143,7 +148,7 @@ internal static bool ColorsEqual(this System.Drawing.Color a, Color b)
143 148
         /// <summary>
144 149
         /// Compresses TextureContent in a format appropriate to the platform
145 150
         /// </summary>
146  
-        public static void CompressTexture(TextureContent content, TargetPlatform platform, bool premultipliedAlpha)
  151
+        public static void CompressTexture(TextureContent content, TargetPlatform platform, bool generateMipmaps, bool premultipliedAlpha)
147 152
         {
148 153
             // TODO: At the moment, only DXT compression from windows machine is supported
149 154
             // Add more here as they become available.
@@ -159,11 +164,11 @@ public static void CompressTexture(TextureContent content, TargetPlatform platfo
159 164
                 case TargetPlatform.MacOSX:
160 165
                 case TargetPlatform.NativeClient:
161 166
                 case TargetPlatform.Xbox360:
162  
-                    CompressDXT(content);
  167
+                    CompressDXT(content, generateMipmaps);
163 168
                     break;
164 169
 
165 170
                 case TargetPlatform.iOS:
166  
-                    CompressPVRTC(content, premultipliedAlpha);
  171
+                    CompressPVRTC(content, generateMipmaps, premultipliedAlpha);
167 172
                     break;
168 173
 
169 174
                 default:
@@ -171,22 +176,37 @@ public static void CompressTexture(TextureContent content, TargetPlatform platfo
171 176
             }
172 177
         }
173 178
 
174  
-        private static void CompressPVRTC(TextureContent content, bool premultipliedAlpha)
  179
+        private static void CompressPVRTC(TextureContent content, bool generateMipmaps, bool premultipliedAlpha)
175 180
         {
176  
-            // Note: MipGeneration will be done by NVTT, rather than PVRTC's tool.
177  
-            // This way we have the same implementation across platforms.
  181
+            // TODO: Once uncompressed mipmap generation is supported, first use NVTT to generate mipmaps,
  182
+            // then compress them withthe PVRTC tool, so we have the same implementation of mipmap generation
  183
+            // across platforms.
  184
+
  185
+            // Calculate number of mip levels
  186
+            var width = content.Faces[0][0].Height;
  187
+            var height = content.Faces[0][0].Width;
  188
+            var numberOfMipLevels = 1;
  189
+            if (generateMipmaps)
  190
+            {
  191
+                while (height != 1 || width != 1)
  192
+                {
  193
+                    height = Math.Max(height / 2, 1);
  194
+                    width = Math.Max(width / 2, 1);
  195
+                    numberOfMipLevels++;
  196
+                }
  197
+            }
178 198
 
179 199
             IntPtr dataSizesPtr = IntPtr.Zero;
180 200
             var texDataPtr = ManagedPVRTC.ManagedPVRTC.CompressTexture(content.Faces[0][0].GetPixelData(),
181 201
                                             content.Faces[0][0].Height,
182 202
                                             content.Faces[0][0].Width,
183  
-                                            1,
  203
+                                            numberOfMipLevels,
184 204
                                             premultipliedAlpha,
185 205
                                             true,
186 206
                                             ref dataSizesPtr);
187 207
 
188  
-            // Store the size of each mipLevel
189  
-            var dataSizesArray = new int[1];
  208
+            // Store the size of each mip level
  209
+            var dataSizesArray = new int[numberOfMipLevels];
190 210
             Marshal.Copy(dataSizesPtr, dataSizesArray, 0, dataSizesArray.Length);
191 211
 
192 212
             var levelSize = 0;
@@ -196,17 +216,25 @@ private static void CompressPVRTC(TextureContent content, bool premultipliedAlph
196 216
 
197 217
             content.Faces[0].Clear();
198 218
 
199  
-            levelSize = dataSizesArray[0];
200  
-            levelData = new byte[levelSize];
  219
+            for (int x = 0; x < numberOfMipLevels; x++)
  220
+            {
  221
+                levelSize = dataSizesArray[x];
  222
+                levelData = new byte[levelSize];
  223
+
  224
+                Marshal.Copy(texDataPtr, levelData, 0, levelSize);
201 225
 
202  
-            Marshal.Copy(texDataPtr, levelData, 0, levelSize);
  226
+                var levelWidth = Math.Max(sourceWidth >> x, 1);
  227
+                var levelHeight = Math.Max(sourceHeight >> x, 1);
203 228
 
204  
-            var bmpContent = new PVRTCBitmapContent(4, sourceWidth, sourceHeight);
205  
-            bmpContent.SetPixelData(levelData);
206  
-            content.Faces[0].Add(bmpContent);
  229
+                var bmpContent = new PVRTCBitmapContent(4, sourceWidth, sourceHeight);
  230
+                bmpContent.SetPixelData(levelData);
  231
+                content.Faces[0].Add(bmpContent);
  232
+
  233
+                texDataPtr = IntPtr.Add(texDataPtr, levelSize);
  234
+            }
207 235
         }
208 236
 
209  
-        private static void CompressDXT(TextureContent content)
  237
+        private static void CompressDXT(TextureContent content, bool generateMipmaps)
210 238
         {
211 239
             var texData = content.Faces[0][0];
212 240
 
@@ -227,7 +255,7 @@ private static void CompressDXT(TextureContent content)
227 255
             var dataPtr = dataHandle.AddrOfPinnedObject();
228 256
 
229 257
             inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
230  
-            inputOptions.SetMipmapGeneration(false);
  258
+            inputOptions.SetMipmapGeneration(generateMipmaps);
231 259
 
232 260
             var containsFracAlpha = ContainsFractionalAlpha(pixelData);
233 261
             var outputOptions = new OutputOptions();
2  MonoGame.Framework.Content.Pipeline/Processors/FontDescriptionProcessor.cs
@@ -138,7 +138,7 @@ public class FontDescriptionProcessor : ContentProcessor<FontDescription, Sprite
138 138
                 output.Texture.Faces.Add(new MipmapChain(bitmapContent));
139 139
             }
140 140
 
141  
-            GraphicsUtil.CompressTexture(output.Texture, context.TargetPlatform, false);
  141
+            GraphicsUtil.CompressTexture(output.Texture, context.TargetPlatform, false, false);
142 142
 
143 143
             return output;
144 144
         }
7  MonoGame.Framework.Content.Pipeline/Processors/TextureProcessor.cs
@@ -68,10 +68,7 @@ public override TextureContent Process(TextureContent input, ContentProcessorCon
68 68
                 }
69 69
             }
70 70
 
71  
-            if (GenerateMipmaps)
72  
-                throw new NotImplementedException();
73  
-
74  
-            // TODO: Set all mip level data
  71
+            // Set the first layer
75 72
             input.Faces[0][0].SetPixelData(input._bitmap.GetData());
76 73
 
77 74
             if (TextureFormat == TextureProcessorOutputFormat.NoChange)
@@ -79,7 +76,7 @@ public override TextureContent Process(TextureContent input, ContentProcessorCon
79 76
 
80 77
             if (TextureFormat == TextureProcessorOutputFormat.DXTCompressed || 
81 78
                 TextureFormat == TextureProcessorOutputFormat.Compressed )
82  
-                GraphicsUtil.CompressTexture(input, context.TargetPlatform, PremultiplyAlpha);
  79
+                GraphicsUtil.CompressTexture(input, context.TargetPlatform, GenerateMipmaps, PremultiplyAlpha);
83 80
 
84 81
             return input;
85 82
         }
1  Tools/MGCB/BuildContent.cs
@@ -98,6 +98,7 @@ public void AddProcessorParam(string nameAndValue)
98 98
                 return;
99 99
             }
100 100
 
  101
+            _processorParams.Remove(keyAndValue[0]);
101 102
             _processorParams.Add(keyAndValue[0], keyAndValue[1]);
102 103
         }
103 104
 
4  Tools/MGCB/Program.cs
@@ -5,6 +5,7 @@
5 5
 using System;
6 6
 using System.IO;
7 7
 using System.Linq;
  8
+using System.Reflection;
8 9
 using System.Runtime.InteropServices;
9 10
 
10 11
 namespace MGCB
@@ -22,7 +23,8 @@ static int Main(string[] args)
22 23
 #if WINDOWS
23 24
             // Set the correct directory for our dependency files.
24 25
             var is32Bit = IntPtr.Size == 4;
25  
-            var directory = string.Format("Dependencies{0}{1}", Path.DirectorySeparatorChar, is32Bit ? "x32" : "x64");
  26
+            var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
  27
+                string.Format("Dependencies{0}{1}", Path.DirectorySeparatorChar, is32Bit ? "x32" : "x64"));
26 28
             SetDllDirectory(directory);
27 29
 #endif
28 30
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.