//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// "draw" python API function
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool BlenderSession::draw(int w, int h) {
    BufferParams    buffer_params;
    bool            reset = false;

	// Before drawing, we verify camera and viewport size changes, because
	// we do not get update callbacks for those, we must detect them here
	if(session->ready_to_reset()) {
		// Try to acquire mutex. If we can't, come back later.
        if(!session->scene->mutex.try_lock())
            tag_redraw();
		else {
			sync->sync_view(b_v3d, b_rv3d, w, h);
			session->scene->mutex.unlock();
		}

		// If dimensions changed, reset
		if(width != w || height != h) {
			width   = w;
			height  = h;
			reset   = true;
		}

		// Reset if requested
        if(reset) {
			buffer_params = BlenderSync::get_display_buffer_params(scene->camera, w, h);

            session->update(buffer_params);
		}
	}

	// Update status and progress for 3d view draw
	update_status_progress();

	// Draw
    if(!reset) buffer_params = BlenderSync::get_display_buffer_params(scene->camera, width, height);
    if(!session->draw(buffer_params)) {
        session->update(buffer_params);
        if(!session->draw(buffer_params)) tag_redraw();
    }
    return true;
} //draw()
bool BlenderSession::draw(int w, int h)
{
	/* pause in redraw in case update is not being called due to final render */
	session->set_pause(BlenderSync::get_session_pause(b_scene, background));

	/* before drawing, we verify camera and viewport size changes, because
	 * we do not get update callbacks for those, we must detect them here */
	if(session->ready_to_reset()) {
		bool reset = false;

		/* if dimensions changed, reset */
		if(width != w || height != h) {
			if(start_resize_time == 0.0) {
				/* don't react immediately to resizes to avoid flickery resizing
				 * of the viewport, and some window managers changing the window
				 * size temporarily on unminimize */
				start_resize_time = time_dt();
				tag_redraw();
			}
			else if(time_dt() - start_resize_time < 0.2) {
				tag_redraw();
			}
			else {
				width = w;
				height = h;
				reset = true;
			}
		}

		/* try to acquire mutex. if we can't, come back later */
		if(!session->scene->mutex.try_lock()) {
			tag_update();
		}
		else {
			/* update camera from 3d view */

			sync->sync_view(b_v3d, b_rv3d, width, height);

			if(scene->camera->need_update)
				reset = true;

			session->scene->mutex.unlock();
		}

		/* reset if requested */
		if(reset) {
			SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
			BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
			bool session_pause = BlenderSync::get_session_pause(b_scene, background);

			if(session_pause == false) {
				session->reset(buffer_params, session_params.samples);
				start_resize_time = 0.0;
			}
		}
	}
	else {
		tag_update();
	}

	/* update status and progress for 3d view draw */
	update_status_progress();

	/* draw */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
	DeviceDrawParams draw_params;

	if(session->params.display_buffer_linear) {
		draw_params.bind_display_space_shader_cb = function_bind(&BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
		draw_params.unbind_display_space_shader_cb = function_bind(&BL::RenderEngine::unbind_display_space_shader, &b_engine);
	}

	return !session->draw(buffer_params, draw_params);
}