void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
 {
     // Request redrawing when it is available again
     if ((bool)e.NewValue) Invalidate();
     else
     {
         // D3DImage is no so good to handle availability changing,
         // so make things carefully as possible
         if (renderTarget != null) renderTarget.Dispose();
         renderTarget = null;
     }
 }
        /// <summary>
        /// Refreshes output content
        /// </summary>
        void Update()
        {
            // Skip if something missing
            if (camera == null || render == null) return;

            d3dImage.Lock();

            // Check whether current render target exists and has appropriate size
            if (renderTarget == null || (int)RenderSize.Width != renderTarget.Width || (int)RenderSize.Height != renderTarget.Height)
            {
                if (renderTarget != null) renderTarget.Dispose();
                renderTarget = new RenderTarget((int)RenderSize.Width, (int)RenderSize.Height);
            }
            // Set it as current
            d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, renderTarget.Handle);

            // Render to it & unlock
            render.Draw(renderTarget, camera);
            d3dImage.AddDirtyRect(new Int32Rect(0, 0, renderTarget.Width, renderTarget.Height));
            d3dImage.Unlock();
        }
        /// <summary>
        /// Renders the content to the render target
        /// </summary>
        /// <param name="renderTarget">Render target</param>
        /// <param name="camera">Camera</param>
        public void Draw(RenderTarget renderTarget, Camera camera)
        {
            // Upload atom's data
            if (!atomsUploaded) { UploadAtoms(); atomsUploaded = true; }
            // Upload bonds's data
            if (!bondsUploaded) { UploadBonds(); bondsUploaded = true; }
            // Upload bonds's render options
            if (!bondRenderOptionsUploaded) { UploadBondRenderOptions(); bondRenderOptionsUploaded = true; }
            // Upload elements materials data
            if (!elementMaterialsUploaded) { UploadElementMaterials(); elementMaterialsUploaded = true; }
            // Upload ribbons data
            if (!residuesUploaded) { UploadResidues(); residuesUploaded = true; }
            // Upload ribbons material's data
            if (!residuesMaterialsUploaded) { UploadResidueMaterials(); residuesMaterialsUploaded = true; }

            // Rendering
            Matrix3D viewMatrix = camera.View;
            Matrix3D projectionMatrix = camera.Projection;

            IntPtr viewMatrixPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Matrix3D)));
            IntPtr projectionMatrixPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Matrix3D)));
            Marshal.StructureToPtr(viewMatrix, viewMatrixPointer, false);
            Marshal.StructureToPtr(projectionMatrix, projectionMatrixPointer, false);

            try
            {
                RenderTo(handle, renderTarget.Handle, viewMatrixPointer, projectionMatrixPointer);
            }
            finally
            {
                Marshal.FreeHGlobal(viewMatrixPointer);
                Marshal.FreeHGlobal(projectionMatrixPointer);
            }
        }