Beispiel #1
0
        private void GL_popState()
        {
            // End the effect, restoring the previous shader state
            FNA3D.FNA3D_EndPassRestore(
                currentDevice.GLDevice,
                shaderProgram.glEffect
                );

            // Restore GL state
            currentDevice.BlendState        = prevBlend;
            currentDevice.DepthStencilState = prevDepthStencil;
            currentDevice.RasterizerState   = prevRasterizer;
            prevBlend        = null;
            prevDepthStencil = null;
            prevRasterizer   = null;

            /* Restore targets using GLDevice directly.
             * This prevents accidental clearing of previously bound targets.
             */
            if (oldTargets == null || oldTargets.Length == 0)
            {
                FNA3D.FNA3D_SetRenderTargets(
                    currentDevice.GLDevice,
                    IntPtr.Zero,
                    0,
                    IntPtr.Zero,
                    DepthFormat.None,
                    0
                    );
            }
            else
            {
                IRenderTarget oldTarget = oldTargets[0].RenderTarget as IRenderTarget;

                unsafe
                {
                    fixed(FNA3D.FNA3D_RenderTargetBinding *rt = &nativeOldTargets[0])
                    {
                        GraphicsDevice.PrepareRenderTargetBindings(
                            rt,
                            oldTargets
                            );
                        FNA3D.FNA3D_SetRenderTargets(
                            currentDevice.GLDevice,
                            rt,
                            oldTargets.Length,
                            oldTarget.DepthStencilBuffer,
                            oldTarget.DepthStencilFormat,
                            (byte)(oldTarget.RenderTargetUsage != RenderTargetUsage.DiscardContents ? 1 : 0)                              /* lol c# */
                            );
                    }
                }
            }
            oldTargets = null;

            // Set viewport AFTER setting targets!
            FNA3D.FNA3D_SetViewport(
                currentDevice.GLDevice,
                ref prevViewport.viewport
                );

            // Restore buffers
            currentDevice.SetVertexBuffers(oldBuffers);
            oldBuffers = null;

            // Restore samplers
            currentDevice.Textures.ignoreTargets = true;
            for (int i = 0; i < 3; i += 1)
            {
                /* The application may have set a texture ages
                 * ago, only to not unset after disposing. We
                 * have to avoid an ObjectDisposedException!
                 */
                if (oldTextures[i] == null || !oldTextures[i].IsDisposed)
                {
                    currentDevice.Textures[i] = oldTextures[i];
                }
                currentDevice.SamplerStates[i] = oldSamplers[i];
                oldTextures[i] = null;
                oldSamplers[i] = null;
            }
            currentDevice.Textures.ignoreTargets = false;
        }
        protected internal override Texture2D Read(
            ContentReader reader,
            Texture2D existingInstance
            )
        {
            Texture2D texture = null;

            SurfaceFormat surfaceFormat;

            if (reader.version < 5)
            {
                /* These integer values are based on the enum values
                 * from previous XNA versions.
                 * -flibit
                 */
                int legacyFormat = reader.ReadInt32();
                if (legacyFormat == 1)
                {
                    surfaceFormat = SurfaceFormat.ColorBgraEXT;
                }
                else if (legacyFormat == 28)
                {
                    surfaceFormat = SurfaceFormat.Dxt1;
                }
                else if (legacyFormat == 30)
                {
                    surfaceFormat = SurfaceFormat.Dxt3;
                }
                else if (legacyFormat == 32)
                {
                    surfaceFormat = SurfaceFormat.Dxt5;
                }
                else
                {
                    throw new NotSupportedException(
                              "Unsupported legacy surface format."
                              );
                }
            }
            else
            {
                surfaceFormat = (SurfaceFormat)reader.ReadInt32();
            }
            int width            = reader.ReadInt32();
            int height           = reader.ReadInt32();
            int levelCount       = reader.ReadInt32();
            int levelCountOutput = levelCount;

            GraphicsDevice device = GraphicsDeviceManager.Instance.GraphicsDevice;

            // Check to see if we need to convert the surface data
            SurfaceFormat convertedFormat = surfaceFormat;

            if (surfaceFormat == SurfaceFormat.Dxt1 &&
                FNA3D.FNA3D_SupportsDXT1(device.GLDevice) == 0)
            {
                convertedFormat = SurfaceFormat.Color;
            }
            else if ((surfaceFormat == SurfaceFormat.Dxt3 ||
                      surfaceFormat == SurfaceFormat.Dxt5) &&
                     FNA3D.FNA3D_SupportsS3TC(device.GLDevice) == 0)
            {
                convertedFormat = SurfaceFormat.Color;
            }

            // Check for duplicate instances
            if (existingInstance == null)
            {
                texture = new Texture2D(
                    width,
                    height,
                    levelCountOutput > 1,
                    convertedFormat
                    );
            }
            else
            {
                texture = existingInstance;
            }

            for (int level = 0; level < levelCount; level += 1)
            {
                int    levelDataSizeInBytes = reader.ReadInt32();
                byte[] levelData            = null;      // Don't assign this quite yet...
                int    levelWidth           = width >> level;
                int    levelHeight          = height >> level;
                if (level >= levelCountOutput)
                {
                    continue;
                }

                // Swap the image data if required.
                if (reader.platform == 'x')
                {
                    if (surfaceFormat == SurfaceFormat.Color ||
                        surfaceFormat == SurfaceFormat.ColorBgraEXT)
                    {
                        levelData = X360TexUtil.SwapColor(
                            reader.ReadBytes(levelDataSizeInBytes)
                            );
                        levelDataSizeInBytes = levelData.Length;
                    }
                    else if (surfaceFormat == SurfaceFormat.Dxt1)
                    {
                        levelData = X360TexUtil.SwapDxt1(
                            reader.ReadBytes(levelDataSizeInBytes),
                            levelWidth,
                            levelHeight
                            );
                        levelDataSizeInBytes = levelData.Length;
                    }
                    else if (surfaceFormat == SurfaceFormat.Dxt3)
                    {
                        levelData = X360TexUtil.SwapDxt3(
                            reader.ReadBytes(levelDataSizeInBytes),
                            levelWidth,
                            levelHeight
                            );
                        levelDataSizeInBytes = levelData.Length;
                    }
                    else if (surfaceFormat == SurfaceFormat.Dxt5)
                    {
                        levelData = X360TexUtil.SwapDxt5(
                            reader.ReadBytes(levelDataSizeInBytes),
                            levelWidth,
                            levelHeight
                            );
                        levelDataSizeInBytes = levelData.Length;
                    }
                }

                // Convert the image data if required
                if (convertedFormat != surfaceFormat)
                {
                    // May already be read in by 'x' conversion
                    if (levelData == null)
                    {
                        levelData = reader.ReadBytes(levelDataSizeInBytes);
                    }
                    if (surfaceFormat == SurfaceFormat.Dxt1)
                    {
                        levelData = DxtUtil.DecompressDxt1(
                            levelData,
                            levelWidth,
                            levelHeight
                            );
                    }
                    else if (surfaceFormat == SurfaceFormat.Dxt3)
                    {
                        levelData = DxtUtil.DecompressDxt3(
                            levelData,
                            levelWidth,
                            levelHeight
                            );
                    }
                    else if (surfaceFormat == SurfaceFormat.Dxt5)
                    {
                        levelData = DxtUtil.DecompressDxt5(
                            levelData,
                            levelWidth,
                            levelHeight
                            );
                    }
                    levelDataSizeInBytes = levelData.Length;
                }

                int levelDataByteOffset = 0;
                if (levelData == null)
                {
                    if (reader.BaseStream is MemoryStream &&
                        ((MemoryStream)reader.BaseStream).TryGetBuffer(out levelData))
                    {
                        /* Ideally, we didn't have to perform any conversion or
                         * unnecessary reading. Just throw the buffer directly
                         * into SetData, skipping a redundant byte[] copy.
                         */
                        levelDataByteOffset = (int)reader.BaseStream.Seek(0, SeekOrigin.Current);
                        reader.BaseStream.Seek(
                            levelDataSizeInBytes,
                            SeekOrigin.Current
                            );
                    }
                    else
                    {
                        /* If we don't have to perform any conversion and
                         * the ContentReader is not backed by a MemoryStream
                         * with a public buffer, we have to read the data in.
                         */
                        levelData = reader.ReadBytes(levelDataSizeInBytes);
                    }
                }
                texture.SetData(
                    level,
                    null,
                    levelData,
                    levelDataByteOffset,
                    levelDataSizeInBytes
                    );
            }

            return(texture);
        }
Beispiel #3
0
        private void INTERNAL_CreateGraphicsDeviceInformation(
            GraphicsDeviceInformation gdi
            )
        {
            /* Apply the GraphicsDevice changes to the new Parameters.
             * Note that PreparingDeviceSettings can override any of these!
             * -flibit
             */
            if (useResizedBackBuffer)
            {
                gdi.PresentationParameters.BackBufferWidth =
                    resizedBackBufferWidth;
                gdi.PresentationParameters.BackBufferHeight =
                    resizedBackBufferHeight;
                useResizedBackBuffer = false;
            }
            else
            {
                if (!supportsOrientations)
                {
                    gdi.PresentationParameters.BackBufferWidth =
                        PreferredBackBufferWidth;
                    gdi.PresentationParameters.BackBufferHeight =
                        PreferredBackBufferHeight;
                }
                else
                {
                    /* Flip the backbuffer dimensions to scale
                     * appropriately to the current orientation.
                     */
                    int min = Math.Min(PreferredBackBufferWidth, PreferredBackBufferHeight);
                    int max = Math.Max(PreferredBackBufferWidth, PreferredBackBufferHeight);

                    if (gdi.PresentationParameters.DisplayOrientation == DisplayOrientation.Portrait)
                    {
                        gdi.PresentationParameters.BackBufferWidth  = min;
                        gdi.PresentationParameters.BackBufferHeight = max;
                    }
                    else
                    {
                        gdi.PresentationParameters.BackBufferWidth  = max;
                        gdi.PresentationParameters.BackBufferHeight = min;
                    }
                }
            }
            gdi.PresentationParameters.BackBufferFormat =
                PreferredBackBufferFormat;
            gdi.PresentationParameters.DepthStencilFormat =
                PreferredDepthStencilFormat;
            gdi.PresentationParameters.IsFullScreen =
                IsFullScreen;
            gdi.PresentationParameters.PresentationInterval =
                SynchronizeWithVerticalRetrace ?
                PresentInterval.One :
                PresentInterval.Immediate;
            if (!PreferMultiSampling)
            {
                gdi.PresentationParameters.MultiSampleCount = 0;
            }
            else if (gdi.PresentationParameters.MultiSampleCount == 0)
            {
                /* XNA4 seems to have an upper limit of 8, but I'm willing to
                 * limit this only in GraphicsDeviceManager's default setting.
                 * If you want even higher values, Reset() with a custom value.
                 * -flibit
                 */
                int maxMultiSampleCount = 0;
                if (graphicsDevice != null)
                {
                    maxMultiSampleCount = FNA3D.FNA3D_GetMaxMultiSampleCount(
                        graphicsDevice.GLDevice,
                        gdi.PresentationParameters.BackBufferFormat,
                        8
                        );
                }
                gdi.PresentationParameters.MultiSampleCount = Math.Min(
                    maxMultiSampleCount,
                    8
                    );
            }
            gdi.GraphicsProfile = GraphicsProfile;

            // Give the user a chance to override the above settings.
            OnPreparingDeviceSettings(
                this,
                new PreparingDeviceSettingsEventArgs(gdi)
                );
        }