/*
 * Copyright (c) 2011, Oracle  and/or its affiliates. All rights reserved.
 *
 * Use is subject to license terms.
 */

package com.sun.javafx.tk.quantum;

import com.sun.prism.Graphics;
import com.sun.prism.impl.Disposer;


/**
 * @author Morris Meyer
 */
public class PresentingPainter extends ViewPainter implements Runnable {
    
    private ViewScene   vs;
    
    protected PresentingPainter(ViewScene view, PrismPen pen) {
        super(view, pen);
        vs = view;
    }

    @Override public void run() {
        try {
            assert !renderLock.isHeldByCurrentThread();
            renderLock.lock();

            valid = validateStageGraphics();

            if (!valid) {
                if (verbose) {
                    System.err.println("PresentingPainter: validateStageGraphics failed");
                }
                return;
            }
            
            if (view != null) {
                /*
                 * As Glass is responsible for creating the rendering contexts,
                 * pen.begin should be done prior to the Prism calls.
                 */
                pen.begin();
            }

            boolean needsReset = (presentable == null) || (penWidth != viewWidth) || (penHeight != viewHeight);
            if (needsReset) {
                if (presentable == null || presentable.recreateOnResize()) {
                    context = factory.createRenderingContext(vs.getPlatformView());
                }
            }
            
            context.begin();
            
            if (needsReset) {
                if (presentable == null || presentable.recreateOnResize()) {
                    disposePresentable();
                    presentable = factory.createPresentable(vs.getPlatformView());
                    needsReset = false;
                }
                penWidth  = viewWidth;
                penHeight = viewHeight;
            }
            
            if (presentable != null) {
                Graphics g = presentable.createGraphics();

                if (g != null) {
                    if (needsReset) {
                        g.reset();
                    }
                    paintImpl(g);
                }
                
                if (!presentable.prepare(null)) {
                    disposePresentable();
                    scene.entireSceneNeedsRepaint();
                    return;
                }
                
                if (liveRepaint.get() == false && collector.toolkit().isVsyncEnabled()) {
                    collector.releaseScene(scene);
                }

                /* present for vsync buffer swap */
                if (!presentable.present()) {
                    disposePresentable();
                    scene.entireSceneNeedsRepaint();
                }
            }
        } catch (Throwable th) {
            th.printStackTrace(System.err);
        } finally {
            if (valid && context != null) {
                Disposer.cleanUp();
                context.end();            
            }
            if (valid && view != null && view.isClosed() == false) {
                pen.end(); 
            }

            pen.getPainting().set(false);

            renderLock.unlock();
        }
    }
}
