public override void Render(RenderContext parentRenderContext)
    {
      Effect effect = Effect;
      if (!IsVisible || effect == null)
        return;

      RectangleF bounds = ActualBounds;
      if (bounds.Width <= 0 || bounds.Height <= 0)
        return;

      Matrix? layoutTransformMatrix = LayoutTransform == null ? new Matrix?() : LayoutTransform.GetTransform();
      Matrix? renderTransformMatrix = RenderTransform == null ? new Matrix?() : RenderTransform.GetTransform();

      RenderContext localRenderContext = parentRenderContext.Derive(bounds, layoutTransformMatrix, renderTransformMatrix, RenderTransformOrigin, Opacity);
      _inverseFinalTransform = Matrix.Invert(localRenderContext.Transform);

      DeviceEx device = SkinContext.Device;
      Surface backBuffer = device.GetRenderTarget(0);
      SurfaceDescription desc = backBuffer.Description;
      SurfaceDescription? textureDesc = _texture == null ? new SurfaceDescription?() : _texture.GetLevelDescription(0);
      if (!textureDesc.HasValue || textureDesc.Value.Width != desc.Width || textureDesc.Value.Height != desc.Height)
      {
        TryDispose(ref _texture);
        _texture = new Texture(device, desc.Width, desc.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
      }
      using (Surface destSurfaceRef = _texture.GetSurfaceLevel(0))
        device.StretchRectangle(backBuffer, destSurfaceRef, TextureFilter.None);

      UpdateEffectMask(effect, localRenderContext.OccupiedTransformedBounds, desc.Width, desc.Height, localRenderContext.ZOrder);
      if (effect.BeginRender(_texture, new RenderContext(Matrix.Identity, 1.0d, bounds, localRenderContext.ZOrder)))
      {
        _effectContext.Render(0);
        effect.EndRender();
      }
    }
示例#2
0
    public override void Render(RenderContext parentRenderContext)
    {
      if (!IsVisible)
        return;

      RectangleF bounds = ActualBounds;
      if (bounds.Width <= 0 || bounds.Height <= 0)
        return;

      Matrix? layoutTransformMatrix = LayoutTransform == null ? new Matrix?() : LayoutTransform.GetTransform();
      Matrix? renderTransformMatrix = RenderTransform == null ? new Matrix?() : RenderTransform.GetTransform();

      RenderContext localRenderContext = parentRenderContext.Derive(bounds, layoutTransformMatrix, renderTransformMatrix, RenderTransformOrigin, Opacity);
      Matrix finalTransform = localRenderContext.Transform;
      if (finalTransform != _finalTransform)
      {
        _finalTransform = finalTransform;
        _inverseFinalTransform = Matrix.Invert(_finalTransform.Value);
        _renderedBoundingBox = CalculateBoundingBox(_innerRect, finalTransform);
      }

      Brushes.Brush opacityMask = OpacityMask;
      Effect effect = Effect;
      if (opacityMask == null && effect == null)
        // Simply render without opacity mask
        RenderOverride(localRenderContext);
      else
      {
        // Control has an opacity mask or Effect
        // Get global render surface and render texture or create them if they doesn't exist
        RenderTextureAsset renderTexture = ContentManager.Instance.GetRenderTexture(GLOBAL_RENDER_TEXTURE_ASSET_KEY);

        // Ensure they are allocated
        renderTexture.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
        if (!renderTexture.IsAllocated)
          return;

        // Morpheus_xx: these are typical performance results comparing direct rendering to texture and rendering 
        // to surfaces (for multisampling support).

        // Results inside GUI-Test OpacityMask screen for default skin (720p windowed / fullscreen 1080p)
        // Surface + full StretchRect -> Texture    : 350 fps / 174 fps 
        // Texture                                  : 485 fps / 265 fps

        // After OpacityMask fix:
        // Surface + full StretchRect -> Texture    : 250 fps / 155 fps 
        // Surface + Occupied Rect -> Texture       : 325 fps / 204 fps 
        // Texture                                  : 330 fps / 213 fps

        // Results inside GUI-Test OpacityMask screen for Reflexion skin (fullscreen 1080p)
        // Surface + full StretchRect -> Texture    : 142 fps
        // Texture                                  : 235 fps

        // Create a temporary render context and render the control to the render texture
        RenderContext tempRenderContext = new RenderContext(localRenderContext.Transform, localRenderContext.Opacity, bounds, localRenderContext.ZOrder);

        // If no effect is applied, clear only the area of the control, not whole render target (performance!)
        tempRenderContext.ClearOccupiedAreaOnly = effect == null;

        // An additional copy step is only required for multisampling surfaces
        bool isMultiSample = GraphicsDevice.Setup.IsMultiSample;
        if (isMultiSample)
        {
          RenderTargetAsset renderSurface = ContentManager.Instance.GetRenderTarget(GLOBAL_RENDER_SURFACE_ASSET_KEY);
          renderSurface.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
          if (!renderSurface.IsAllocated)
            return;

          // First render to the multisampled surface
          RenderToSurface(renderSurface, tempRenderContext);

          // Unfortunately, brushes/brush effects are based on textures and cannot work with surfaces, so we need this additional copy step
          // Morpheus_xx, 03/2013: changed to copy only the occupied area of Surface, instead of complete area. This improves performance a lot.
          GraphicsDevice.Device.StretchRectangle(
              renderSurface.Surface, ToRect(tempRenderContext.OccupiedTransformedBounds, renderSurface.Size), // new Rectangle(new Point(), renderSurface.Size),
              renderTexture.Surface0, ToRect(tempRenderContext.OccupiedTransformedBounds, renderTexture.Size), // new Rectangle(new Point(), renderTexture.Size),
              TextureFilter.None);
        }
        else
        {
          // Directly render to texture
          RenderToTexture(renderTexture, tempRenderContext);
        }

        // Render Effect
        if (effect == null)
        {
          // Use a default effect to draw the render target if none is set
          if (_defaultEffect == null)
          {
            _defaultEffect = new SimpleShaderEffect { ShaderEffectName = "normal" };
          }

          effect = _defaultEffect;
        }

        UpdateEffectMask(effect, tempRenderContext.OccupiedTransformedBounds, renderTexture.Width, renderTexture.Height, localRenderContext.ZOrder);
        if (effect.BeginRender(renderTexture.Texture, new RenderContext(Matrix.Identity, 1.0d, bounds, localRenderContext.ZOrder)))
        {
          _effectContext.Render(0);
          effect.EndRender();
        }
      }

      // Calculation of absolute render size (in world coordinate system)
      parentRenderContext.IncludeTransformedContentsBounds(localRenderContext.OccupiedTransformedBounds);
      _lastZIndex = localRenderContext.ZOrder;
    }
    public override void Render(RenderContext parentRenderContext)
    {
      if (!IsVisible)
        return;

      RectangleF bounds = ActualBounds;
      if (bounds.Width <= 0 || bounds.Height <= 0)
        return;

      Matrix? layoutTransformMatrix = LayoutTransform == null ? new Matrix?() : LayoutTransform.GetTransform();
      Matrix? renderTransformMatrix = RenderTransform == null ? new Matrix?() : RenderTransform.GetTransform();

      RenderContext localRenderContext = parentRenderContext.Derive(bounds, layoutTransformMatrix,
          renderTransformMatrix, RenderTransformOrigin, Opacity);
       Matrix finalTransform = localRenderContext.Transform;
      if (finalTransform != _finalTransform)
      {
        _finalTransform = finalTransform;
        _inverseFinalTransform = Matrix.Invert(_finalTransform.Value);
        _renderedBoundingBox = CalculateBoundingBox(_innerRect, finalTransform);
      }

      Brushes.Brush opacityMask = OpacityMask;
      if (opacityMask == null && Effect == null)
        // Simply render without opacity mask
        RenderOverride(localRenderContext);
      else
      { 
        // Control has an opacity mask or Effect
        // Get global render surface and render texture or create them if they doesn't exist
        RenderTextureAsset renderTexture = ContentManager.Instance.GetRenderTexture(GLOBAL_RENDER_TEXTURE_ASSET_KEY);

        // Ensure they are allocated
        renderTexture.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
        if (!renderTexture.IsAllocated)
          return;

        // Morpheus_xx: these are typical performance results comparing direct rendering to texture and rendering 
        // to surfaces (for multisampling support).

        // Results inside GUI-Test OpacityMask screen for default skin (720p windowed / fullscreen 1080p)
        // Surface + full StretchRect -> Texture    : 350 fps / 174 fps 
        // Texture                                  : 485 fps / 265 fps

        // Results inside GUI-Test OpacityMask screen for Reflexion skin (fullscreen 1080p)
        // Surface + full StretchRect -> Texture    : 142 fps
        // Texture                                  : 235 fps

        // Create a temporary render context and render the control to the render texture
        RenderContext tempRenderContext = new RenderContext(localRenderContext.Transform, localRenderContext.Opacity, bounds, localRenderContext.ZOrder);

        // An additional copy step is only required for multisampling surfaces
        bool isMultiSample = GraphicsDevice.Setup.IsMultiSample;
        if (isMultiSample)
        {
          RenderTargetAsset renderSurface = ContentManager.Instance.GetRenderTarget(GLOBAL_RENDER_SURFACE_ASSET_KEY);
          renderSurface.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
          if (!renderSurface.IsAllocated)
            return;

          // First render to the multisampled surface
          RenderToSurface(renderSurface, tempRenderContext);

          // Unfortunately, brushes/brush effects are based on textures and cannot work with surfaces, so we need this additional copy step
          GraphicsDevice.Device.StretchRectangle(
              renderSurface.Surface,  new Rectangle(Point.Empty, renderSurface.Size),
              renderTexture.Surface0, new Rectangle(Point.Empty, renderTexture.Size),
              TextureFilter.None);
        }
        else
          // Directly render to texture
          RenderToTexture(renderTexture, tempRenderContext);

        // Add bounds to our calculated, occupied area.
        // If we don't do that, lines at the border of this element might be dimmed because of the filter (see OpacityMask test in GUITestPlugin).
        // The value was just found by testing. Any better solution is welcome.
        if (opacityMask != null)
        {
          const float OPACITY_MASK_BOUNDS = 0.9f;
          RectangleF occupiedTransformedBounds = tempRenderContext.OccupiedTransformedBounds;
          occupiedTransformedBounds.X -= OPACITY_MASK_BOUNDS;
          occupiedTransformedBounds.Y -= OPACITY_MASK_BOUNDS;
          occupiedTransformedBounds.Width += OPACITY_MASK_BOUNDS * 2;
          occupiedTransformedBounds.Height += OPACITY_MASK_BOUNDS * 2;

          // If the control bounds have changed we need to update our primitive context to make the 
          // texture coordinates match up
          if (_updateOpacityMask || _opacityMaskContext == null ||
              occupiedTransformedBounds != _lastOccupiedTransformedBounds ||
            renderTexture.Size != _lastOpacityRenderSize)
          {
            UpdateOpacityMask(occupiedTransformedBounds, renderTexture.Width, renderTexture.Height, localRenderContext.ZOrder);
            _lastOccupiedTransformedBounds = occupiedTransformedBounds;
            _updateOpacityMask = false;
            _lastOpacityRenderSize = renderTexture.Size;
          }

          // Now render the opacity texture with the OpacityMask brush)
          if (opacityMask.BeginRenderOpacityBrush(renderTexture.Texture, new RenderContext(Matrix.Identity, bounds)))
          {
            _opacityMaskContext.Render(0);
            opacityMask.EndRender();
          }
        }

        // Render Effect
        Effects.Effect effect = Effect;
        if (effect != null)
        {
          UpdateEffectMask(effect, tempRenderContext.OccupiedTransformedBounds, renderTexture.Width, renderTexture.Height, localRenderContext.ZOrder);
          if (effect.BeginRender(renderTexture.Texture, new RenderContext(Matrix.Identity, 1.0d, bounds, localRenderContext.ZOrder)))
          {
            _effectContext.Render(0);
            effect.EndRender();
          }
        }

      }
      // Calculation of absolute render size (in world coordinate system)
      parentRenderContext.IncludeTransformedContentsBounds(localRenderContext.OccupiedTransformedBounds);
      _lastZIndex = localRenderContext.ZOrder;
    }
    public override void Render(RenderContext parentRenderContext)
    {
      if (!IsVisible)
        return;

      RectangleF bounds = ActualBounds;
      if (bounds.Width <= 0 || bounds.Height <= 0)
        return;

      Matrix? layoutTransformMatrix = LayoutTransform == null ? new Matrix?() : LayoutTransform.GetTransform();
      Matrix? renderTransformMatrix = RenderTransform == null ? new Matrix?() : RenderTransform.GetTransform();

      RenderContext localRenderContext = parentRenderContext.Derive(bounds, layoutTransformMatrix,
          renderTransformMatrix, RenderTransformOrigin, Opacity);
      _inverseFinalTransform = Matrix.Invert(localRenderContext.Transform);

      Brushes.Brush opacityMask = OpacityMask;
      if (opacityMask == null && Effect == null)
        // Simply render without opacity mask
        DoRender(localRenderContext);
      else
      { 
        // Control has an opacity mask or Effect
        RenderTextureAsset renderTexture = ContentManager.Instance.GetRenderTexture(GLOBAL_RENDER_TEXTURE_ASSET_KEY);
        // Get global render surface and render texture or create them if they dosn't exist
        RenderTargetAsset renderSurface = ContentManager.Instance.GetRenderTarget(GLOBAL_RENDER_SURFACE_ASSET_KEY);

        // Ensure they are allocated
        renderTexture.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
        renderSurface.AllocateRenderTarget(GraphicsDevice.Width, GraphicsDevice.Height);
        if (!renderTexture.IsAllocated || !renderSurface.IsAllocated)
          return;

        // Create a temporary render context and render the control to the render texture
        RenderContext tempRenderContext = new RenderContext(localRenderContext.Transform, localRenderContext.Opacity, bounds, localRenderContext.ZOrder);
        RenderToSurface(renderSurface, tempRenderContext);

        // Unfortunately, brushes/brush effects are based on textures and cannot work with surfaces, so we need this additional copy step
        GraphicsDevice.Device.StretchRectangle(
            renderSurface.Surface, new Rectangle(Point.Empty, renderSurface.Size),
            renderTexture.Surface0, new Rectangle(Point.Empty, renderTexture.Size),
            TextureFilter.None);

        // Add bounds to our calculated, occupied area.
        // If we don't do that, lines at the border of this element might be dimmed because of the filter (see OpacityMask test in GUITestPlugin).
        // The value was just found by testing. Any better solution is welcome.
        if (opacityMask != null)
        {
          const float OPACITY_MASK_BOUNDS = 0.9f;
          RectangleF occupiedTransformedBounds = tempRenderContext.OccupiedTransformedBounds;
          occupiedTransformedBounds.X -= OPACITY_MASK_BOUNDS;
          occupiedTransformedBounds.Y -= OPACITY_MASK_BOUNDS;
          occupiedTransformedBounds.Width += OPACITY_MASK_BOUNDS * 2;
          occupiedTransformedBounds.Height += OPACITY_MASK_BOUNDS * 2;

          // If the control bounds have changed we need to update our primitive context to make the 
          // texture coordinates match up
          if (_updateOpacityMask || _opacityMaskContext == null ||
              occupiedTransformedBounds != _lastOccupiedTransformedBounds ||
            renderSurface.Size != _lastOpacityRenderSize)
          {
            UpdateOpacityMask(occupiedTransformedBounds, renderSurface.Width, renderSurface.Height, localRenderContext.ZOrder);
            _lastOccupiedTransformedBounds = occupiedTransformedBounds;
            _updateOpacityMask = false;
            _lastOpacityRenderSize = renderSurface.Size;
          }

          // Now render the opacity texture with the OpacityMask brush)
          if (opacityMask.BeginRenderOpacityBrush(renderTexture.Texture, new RenderContext(Matrix.Identity, bounds)))
          {
            _opacityMaskContext.Render(0);
            opacityMask.EndRender();
          }
        }

        // Render Effect
        Effects.Effect effect = Effect;
        if (effect != null)
        {
          UpdateEffectMask(tempRenderContext.OccupiedTransformedBounds, renderTexture.Width, renderTexture.Height, localRenderContext.ZOrder);
          if (effect.BeginRender(renderTexture.Texture, new RenderContext(Matrix.Identity, 1.0d, bounds, localRenderContext.ZOrder)))
          {
            _effectContext.Render(0);
            effect.EndRender();
          }
        }

      }
      // Calculation of absolute render size (in world coordinate system)
      parentRenderContext.IncludeTransformedContentsBounds(localRenderContext.OccupiedTransformedBounds);
      _lastZIndex = localRenderContext.ZOrder;
    }