/*
 * Asynchronous I/O callback launched when framebuffer notifications are ready
 * to be read.
 * Param:
 *  opaque - FrameBufferImpl instance.
 */
static void
_fbUpdatesImpl_io_callback(void* opaque, int fd, unsigned events)
{
    FrameBufferImpl* fbi = opaque;
    int  ret;

    // Read updates while they are immediately available.
    for (;;) {
        // Read next chunk of data.
        ret = HANDLE_EINTR(
                socket_recv(fbi->sock,
                            fbi->reader_buffer + fbi->reader_offset,
                            fbi->reader_bytes - fbi->reader_offset));
        if (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
            // Chunk is not avalable at this point. Come back later.
            return;
        }
        if (ret <= 0) {
            /* disconnection ! */
            derror("Unable to receive framebuffer data: %s\n",
                   ret < 0 ? strerror(errno), "unexpected disconnection");
            fbUpdatesImpl_destroy();
            return;
        }

        fbi->reader_offset += ret;
        if (fbi->reader_offset != fbi->reader_bytes) {
            // There are still some data left in the pipe.
            continue;
        }

        // All expected data has been read. Time to change the state.
        if (fbi->fb_state == EXPECTS_HEADER) {
            // Update header has been read. Prepare for the pixels.
            fbi->fb_state = EXPECTS_PIXELS;
            fbi->reader_offset = 0;
            fbi->reader_bytes = fbi->update_header.w *
                                      fbi->update_header.h *
                                      (fbi->bits_per_pixel / 8);
            fbi->reader_buffer = malloc(fbi->reader_bytes);
            if (fbi->reader_buffer == NULL) {
                APANIC("Unable to allocate memory for framebuffer update\n");
            }
        } else {
            // Pixels have been read. Prepare for the header.
             uint8_t* pixels = fbi->reader_buffer;

            fbi->fb_state = EXPECTS_HEADER;
            fbi->reader_offset = 0;
            fbi->reader_bytes = sizeof(FBUpdateMessage);
            fbi->reader_buffer = (uint8_t*)&fbi->update_header;

            // Perform the update. Note that pixels buffer must be freed there.
            _update_rect(fbi->fb, fbi->update_header.x,
                        fbi->update_header.y, fbi->update_header.w,
                        fbi->update_header.h, fbi->bits_per_pixel,
                        pixels);
        }
    }
Exemple #2
0
void Viewport::set_rect(const Rect2& p_rect) {

	if (rect==p_rect)
		return;
	rect=p_rect;
	_update_rect();
	_update_stretch_transform();

}
Exemple #3
0
void Viewport::set_size_override_stretch(bool p_enable) {

	if (p_enable==size_override_stretch)
		return;

	size_override_stretch=p_enable;
	if (size_override) {
		_update_rect();
	}


	_update_stretch_transform();
}
Exemple #4
0
void Viewport::set_size_override(bool p_enable, const Size2& p_size, const Vector2 &p_margin) {

	if (size_override==p_enable && p_size==size_override_size)
		return;

	size_override=p_enable;
	if (p_size.x>=0 || p_size.y>=0) {
		size_override_size=p_size;
	}
	size_override_margin=p_margin;
	_update_rect();
	_update_stretch_transform();


}
Exemple #5
0
void Viewport::_notification(int p_what) {
	

	switch( p_what ) {
		
		case NOTIFICATION_ENTER_SCENE: {


			if (!render_target)
				_vp_enter_scene();

			this->parent=NULL;
			Node *parent=get_parent();

			if (parent) {


				while(parent && !(this->parent=parent->cast_to<Viewport>())) {

					parent=parent->get_parent();
				}
			}

			current_canvas=find_world_2d()->get_canvas();
			VisualServer::get_singleton()->viewport_set_scenario(viewport,find_world()->get_scenario());
			VisualServer::get_singleton()->viewport_attach_canvas(viewport,current_canvas);

			_update_listener();
			_update_listener_2d();
			_update_rect();

			if (world_2d.is_valid()) {
				find_world_2d()->_register_viewport(this,Rect2());
//best to defer this and not do it here, as it can annoy a lot of setup logic if user
//adds a node and then moves it, will get enter/exit screen/viewport notifications
//unnecesarily
//				update_worlds();
			}

			add_to_group("_viewports");

		} break;
		case NOTIFICATION_READY: {
#ifndef _3D_DISABLED
			if (cameras.size() && !camera) {
				//there are cameras but no current camera, pick first in tree and make it current
				Camera *first=NULL;
				for(Set<Camera*>::Element *E=cameras.front();E;E=E->next()) {

					if (first==NULL || first->is_greater_than(E->get())) {
						first=E->get();
					}
				}

				if (first)
					first->make_current();
			}
#endif
		} break;
		case NOTIFICATION_EXIT_SCENE: {



			if (world_2d.is_valid())
				world_2d->_remove_viewport(this);

			if (!render_target)
				_vp_exit_scene();

			VisualServer::get_singleton()->viewport_set_scenario(viewport,RID());
			SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
			VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
			remove_from_group("_viewports");

		} break;
	}
}
Exemple #6
0
void Viewport::_parent_resized() {

	_update_rect();
}