void ViewBackend::commitBuffer(uint32_t handle, uint32_t width, uint32_t height) { if (handle != elementHandle || width != this->width || height != this->height) return; DISPMANX_UPDATE_HANDLE_T updateHandle = vc_dispmanx_update_start(0); VC_RECT_T srcRect, destRect; vc_dispmanx_rect_set(&srcRect, 0, 0, width << 16, height << 16); vc_dispmanx_rect_set(&destRect, 0, 0, width, height); vc_dispmanx_element_change_attributes(updateHandle, elementHandle, 1 << 3 | 1 << 2, 0, 0, &destRect, &srcRect, 0, DISPMANX_NO_ROTATE); vc_dispmanx_update_submit(updateHandle, [](DISPMANX_UPDATE_HANDLE_T, void* data) { auto& backend = *static_cast<ViewBackend*>(data); struct timeval tv; gettimeofday(&tv, nullptr); uint64_t time = tv.tv_sec * 1000 + tv.tv_usec / 1000; ssize_t ret = write(backend.updateFd, &time, sizeof(time)); if (ret != sizeof(time)) fprintf(stderr, "ViewBackend: failed to write to the update eventfd\n"); }, this); }
/* Warp the mouse to (x,y) */ static void RPI_WarpMouseGlobal(int x, int y) { RPI_CursorData *curdata; DISPMANX_UPDATE_HANDLE_T update; int ret; VC_RECT_T dst_rect; SDL_Mouse *mouse = SDL_GetMouse(); if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; if (curdata->element != DISPMANX_NO_HANDLE) { update = vc_dispmanx_update_start( 10 ); SDL_assert( update ); vc_dispmanx_rect_set( &dst_rect, x, y, curdata->w, curdata->h); ret = vc_dispmanx_element_change_attributes( update, curdata->element, ELEMENT_CHANGE_DEST_RECT, 0, 0, &dst_rect, NULL, DISPMANX_NO_HANDLE, DISPMANX_NO_ROTATE); SDL_assert( ret == DISPMANX_SUCCESS ); /* Submit asynchronously, otherwise the peformance suffers a lot */ ret = vc_dispmanx_update_submit( update, 0, NULL ); SDL_assert( ret == DISPMANX_SUCCESS ); } } }
static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height) { GST_DEBUG ("resizing window from %ux%u to %ux%u", window_egl->native.width, window_egl->native.height, width, height); if (window_egl->display) { VC_RECT_T dst_rect; VC_RECT_T src_rect; GstVideoRectangle src, dst, res; DISPMANX_UPDATE_HANDLE_T dispman_update; VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0 }; /* Center width*height frame inside dp_width*dp_height */ src.w = width; src.h = height; src.x = src.y = 0; dst.w = window_egl->dp_width; dst.h = window_egl->dp_height; dst.x = dst.y = 0; gst_video_sink_center_rect (src, dst, &res, FALSE); dst_rect.x = res.x; dst_rect.y = res.y; dst_rect.width = res.w; dst_rect.height = res.h; src_rect.x = 0; src_rect.y = 0; src_rect.width = width << 16; src_rect.height = height << 16; dispman_update = vc_dispmanx_update_start (0); if (window_egl->native.element) { vc_dispmanx_element_change_attributes (dispman_update, window_egl->native.element, 0x00000110, 0, 0, &dst_rect, &src_rect, 0, 0); } else { window_egl->native.element = vc_dispmanx_element_add (dispman_update, window_egl->display, 0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0, 0); } vc_dispmanx_update_submit_sync (dispman_update); if (GST_GL_WINDOW (window_egl)->resize) GST_GL_WINDOW (window_egl)-> resize (GST_GL_WINDOW (window_egl)->resize_data, width, height); } window_egl->native.width = width; window_egl->native.height = height; }
void ViewBackend::Cursor::handlePointerEvent(struct wpe_input_pointer_event* event) { targetClient.handlePointerEvent(event); DISPMANX_UPDATE_HANDLE_T updateHandle = vc_dispmanx_update_start(0); VC_RECT_T destRect; vc_dispmanx_rect_set(&destRect, event->x, event->y, std::min<uint32_t>(cursorWidth, std::max<uint32_t>(0, displaySize.first - event->x)), std::min<uint32_t>(cursorHeight, std::max<uint32_t>(0, displaySize.second - event->y))); vc_dispmanx_element_change_attributes(updateHandle, cursorHandle, 1 << 2, 0, 0, &destRect, nullptr, DISPMANX_NO_HANDLE, DISPMANX_NO_ROTATE); vc_dispmanx_update_submit_sync(updateHandle); }
void ViewBackendBCMRPi::commitBCMBuffer(uint32_t elementHandle, uint32_t width, uint32_t height) { DISPMANX_UPDATE_HANDLE_T updateHandle = vc_dispmanx_update_start(0); m_width = width; m_height = height; VC_RECT_T srcRect, destRect; vc_dispmanx_rect_set(&srcRect, 0, 0, m_width << 16, m_height << 16); vc_dispmanx_rect_set(&destRect, 0, 0, m_width, m_height); vc_dispmanx_element_change_attributes(updateHandle, m_elementHandle, 1 << 3 | 1 << 2, 0, 0, &destRect, &srcRect, 0, DISPMANX_NO_ROTATE); vc_dispmanx_update_submit_sync(updateHandle); if (m_client) m_client->frameComplete(); }
static void moveDispmanxLayer(EGLNativeWindowType window, const QPoint &pos) { EGL_DISPMANX_WINDOW_T *eglWindow = static_cast<EGL_DISPMANX_WINDOW_T *>(window); QSize size(eglWindow->width, eglWindow->height); VC_RECT_T dst_rect; dst_rect.x = pos.x(); dst_rect.y = pos.y(); dst_rect.width = size.width(); dst_rect.height = size.height(); DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); vc_dispmanx_element_change_attributes(dispman_update, eglWindow->element, ELEMENT_CHANGE_DEST_RECT /*change_flags*/, 0, 0, &dst_rect, NULL, 0, (DISPMANX_TRANSFORM_T)0); vc_dispmanx_update_submit_sync(dispman_update); }
static void *fbCursorUpdater(void *data) { while (1) { DISPMANX_UPDATE_HANDLE_T update; VC_RECT_T dst; sem_wait(&cursor.semaphore); pthread_mutex_lock(&cursor.mutex); dst.x = cursor.x; dst.y = cursor.y; dst.width = cursor.cursorWidth; dst.height = cursor.cursorHeight; pthread_mutex_unlock(&cursor.mutex); update = vc_dispmanx_update_start(0); vc_dispmanx_element_change_attributes(update, cursor.element, 0x4 , 0 , 0, &dst, 0 , 0 , 0 ); vc_dispmanx_update_submit_sync(update); usleep(16666); /* sleep a sixtieth of a second before moving again */ } return NULL; }
static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height, gboolean visible) { GstGLWindow *window = GST_GL_WINDOW (window_egl); GST_DEBUG ("resizing %s window from %ux%u to %ux%u", visible ? "visible" : "invisible", window_egl->native.width, window_egl->native.height, width, height); if (window_egl->display) { VC_RECT_T dst_rect; VC_RECT_T src_rect; GstVideoRectangle src, res; DISPMANX_UPDATE_HANDLE_T dispman_update; uint32_t opacity = visible ? 255 : 0; VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, opacity, 0 }; src.w = width; src.h = height; src.x = src.y = 0; /* If there is no render rectangle, center the width*height frame * inside dp_width*dp_height */ if (window_egl->render_rect.w <= 0 || window_egl->render_rect.h <= 0) { GstVideoRectangle dst; dst.w = window_egl->dp_width; dst.h = window_egl->dp_height; dst.x = dst.y = 0; gst_video_sink_center_rect (src, dst, &res, FALSE); } else { gst_video_sink_center_rect (src, window_egl->render_rect, &res, FALSE); } dst_rect.x = res.x; dst_rect.y = res.y; dst_rect.width = res.w; dst_rect.height = res.h; src_rect.x = 0; src_rect.y = 0; src_rect.width = width << 16; src_rect.height = height << 16; dispman_update = vc_dispmanx_update_start (0); if (window_egl->native.element) { uint32_t change_flags = ELEMENT_CHANGE_OPACITY | ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT; vc_dispmanx_element_change_attributes (dispman_update, window_egl->native.element, change_flags, 0, opacity, &dst_rect, &src_rect, 0, 0); } else { window_egl->native.element = vc_dispmanx_element_add (dispman_update, window_egl->display, 0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0, 0); } vc_dispmanx_update_submit_sync (dispman_update); gst_gl_window_resize (window, width, height); } window_egl->native.width = width; window_egl->native.height = height; }
int rpi_setup_element(int x, int y, Uint32 video_flags, int update) { // this code is based on the work of Ben O'Steen // http://benosteen.wordpress.com/2012/04/27/using-opengl-es-2-0-on-the-raspberry-pi-without-x-windows/ // https://github.com/benosteen/opengles-book-samples/tree/master/Raspi DISPMANX_UPDATE_HANDLE_T dispman_update; VC_RECT_T dst_rect; VC_RECT_T src_rect; VC_DISPMANX_ALPHA_T alpha_descriptor; uint32_t rpi_display_device=DISPMANX_ID_MAIN_LCD; uint32_t display_width; uint32_t display_height; int success; success = graphics_get_display_size(rpi_display_device, &display_width, &display_height); if ( success < 0 ) { con_printf(CON_URGENT, "Could not get RPi display size, assuming 640x480\n"); display_width=640; display_height=480; } if ((uint32_t)x > display_width) { con_printf(CON_URGENT, "RPi: Requested width %d exceeds display width %u, scaling down!\n", x,display_width); x=(int)display_width; } if ((uint32_t)y > display_height) { con_printf(CON_URGENT, "RPi: Requested height %d exceeds display height %u, scaling down!\n", y,display_height); y=(int)display_height; } con_printf(CON_DEBUG, "RPi: display resolution %ux%u, game resolution: %dx%d (%s)\n", display_width, display_height, x, y, (video_flags & SDL_FULLSCREEN)?"fullscreen":"windowed"); if (video_flags & SDL_FULLSCREEN) { /* scale to the full display size... */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = display_width; dst_rect.height= display_height; } else { /* TODO: we could query the position of the X11 window here and try to place the ovelray exactly above that..., we would have to track window movements, though ... */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = (uint32_t)x; dst_rect.height= (uint32_t)y; } src_rect.x = 0; src_rect.y = 0; src_rect.width = ((uint32_t)x)<< 16; src_rect.height =((uint32_t)y)<< 16; /* we do not want our overlay to be blended against the background */ alpha_descriptor.flags=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; alpha_descriptor.opacity=0xffffffff; alpha_descriptor.mask=0; // open display, if we do not already have one ... if (dispman_display == DISPMANX_NO_HANDLE) { con_printf(CON_DEBUG, "RPi: opening display: %u\n",rpi_display_device); dispman_display = vc_dispmanx_display_open(rpi_display_device); if (dispman_display == DISPMANX_NO_HANDLE) { con_printf(CON_URGENT,"RPi: failed to open display: %u\n",rpi_display_device); } } if (dispman_element != DISPMANX_NO_HANDLE) { if (!update) { // if the element already exists, and we cannot update it, so recreate it rpi_destroy_element(); } } else { // if the element does not exist, we cannot do an update update=0; } dispman_update = vc_dispmanx_update_start( 0 ); if (update) { con_printf(CON_DEBUG, "RPi: updating display manager element\n"); vc_dispmanx_element_change_attributes ( dispman_update, nativewindow.element, ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT, 0 /*layer*/, 0 /*opacity*/, &dst_rect, &src_rect, 0 /*mask*/, VC_IMAGE_ROT0 /*transform*/); } else { // create a new element con_printf(CON_DEBUG, "RPi: creating display manager element\n"); dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &alpha_descriptor, NULL /*clamp*/, VC_IMAGE_ROT0 /*transform*/); if (dispman_element == DISPMANX_NO_HANDLE) { con_printf(CON_URGENT,"RPi: failed to creat display manager elemenr\n"); } nativewindow.element = dispman_element; } nativewindow.width = display_width; nativewindow.height = display_height; vc_dispmanx_update_submit_sync( dispman_update ); return 0; }