public FigureRenderer(IGraphicsService graphicsService, int bufferSize)
        {
            if (graphicsService == null)
            {
                throw new ArgumentNullException("graphicsService");
            }
            if (bufferSize <= 0 || bufferSize > MaxBufferSize)
            {
                throw new ArgumentOutOfRangeException("bufferSize", "The buffer size must be in the range [1, " + MaxBufferSize + "].");
            }
            if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach)
            {
                throw new NotSupportedException("The FigureRenderer does not support the Reach profile.");
            }

            _graphicsService = graphicsService;

            Order      = 5;
            BufferSize = bufferSize;
            Options    = FigureRenderOptions.RenderFillAndStroke;

            // Start with a reasonably large capacity to avoid frequent re-allocations.
            _jobs = new ArrayList <Job>(32);

            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            _strokeEffect = OnLoadEffect(graphicsService);
            // ReSharper restore DoNotCallOverridableMethodsInConstructor

            _parameterViewport    = _strokeEffect.Parameters["ViewportSize"];
            _parameterView        = _strokeEffect.Parameters["View"];
            _parameterViewInverse = _strokeEffect.Parameters["ViewInverse"];
            _parameterProjection  = _strokeEffect.Parameters["Projection"];
            _parameterCameraNear  = _strokeEffect.Parameters["CameraNear"];

            var graphicsDevice = graphicsService.GraphicsDevice;

            // Create stroke indices. (The content of the index buffer does not change.)
            var indices = new ushort[bufferSize * 6];

            for (int i = 0; i < bufferSize; i++)
            {
                // Create index buffer for quad (= two triangles, clockwise).
                //   1--2
                //   | /|
                //   |/ |
                //   0--3
                indices[i * 6 + 0] = (ushort)(i * 4 + 0);
                indices[i * 6 + 1] = (ushort)(i * 4 + 1);
                indices[i * 6 + 2] = (ushort)(i * 4 + 2);
                indices[i * 6 + 3] = (ushort)(i * 4 + 0);
                indices[i * 6 + 4] = (ushort)(i * 4 + 2);
                indices[i * 6 + 5] = (ushort)(i * 4 + 3);
            }

            _strokeBatch = new RenderBatch <StrokeVertex, ushort>(
                graphicsDevice,
                StrokeVertex.VertexDeclaration,
                new StrokeVertex[bufferSize * 4],
                true,
                indices,
                false);

            _fillEffect = new BasicEffect(graphicsDevice)
            {
                Alpha                  = 1,
                DiffuseColor           = new Vector3(1, 1, 1),
                FogEnabled             = false,
                PreferPerPixelLighting = false,
                World                  = Matrix.Identity,
                LightingEnabled        = false,
                TextureEnabled         = false,
                VertexColorEnabled     = true,
            };

            _fillBatch = new RenderBatch <VertexPositionColor, ushort>(
                graphicsDevice,
                VertexPositionColor.VertexDeclaration,
                new VertexPositionColor[bufferSize * 3],
                true,
                new ushort[bufferSize * 3],
                true);
        }