static EGLBoolean __eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) { char *device_name = "/dev/dri/card0"; int fd = -1; EGL_DEBUG("%s: %s\n", __FILE__, __func__); // TODO: create server side for wl_kms. if (__wl_kms) return EGL_FALSE; if (__gbm) { fd = gbm_device_get_fd(__gbm); device_name = _gbm_fd_get_device_name(fd); } else { fd = open(device_name, O_RDWR); if (fd < 0) return EGL_FALSE; __gbm = gbm_create_device(fd); } EGL_DEBUG("%s: decice_name=%s\n", __func__, device_name); __wl_kms = wayland_kms_init(display, __wl_display, device_name, fd); return EGL_TRUE; }
void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) { FrameBuffer *fb = static_cast<FrameBuffer *>(data); if (fb->fb) { gbm_device *device = gbm_bo_get_device(bo); drmModeRmFB(gbm_device_get_fd(device), fb->fb); } delete fb; }
void CDRMUtils::DrmFbDestroyCallback(struct gbm_bo *bo, void *data) { struct drm_fb *fb = static_cast<drm_fb *>(data); if(fb->fb_id) { int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo)); drmModeRmFB(drm_fd, fb->fb_id); } delete (fb); }
void DisplayOzone::presentScreen() { if (!mCRTC) { // no monitor return; } // see if pending flip has finished, without blocking int fd = gbm_device_get_fd(mGBM); if (mPending) { pollfd pfd; pfd.fd = fd; pfd.events = POLLIN; if (poll(&pfd, 1, 0) < 0) { std::cerr << "poll failed: " << errno << " " << strerror(errno) << std::endl; } if (pfd.revents & POLLIN) { drmEventContext event; event.version = DRM_EVENT_CONTEXT_VERSION; event.page_flip_handler = pageFlipHandler; drmHandleEvent(fd, &event); } } // if pending flip has finished, schedule next one if (!mPending && mDrawing) { flushGL(); if (mSetCRTC) { if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0, &mConnector->connector_id, 1, mMode)) { std::cerr << "set crtc failed: " << errno << " " << strerror(errno) << std::endl; } mSetCRTC = false; } if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT, this)) { std::cerr << "page flip failed: " << errno << " " << strerror(errno) << std::endl; } mPending = mDrawing; mDrawing = nullptr; } }
void DisplayOzone::terminate() { SafeDelete(mScanning); SafeDelete(mPending); SafeDelete(mDrawing); SafeDelete(mUnused); if (mProgram) { mFunctionsGL->deleteProgram(mProgram); mFunctionsGL->deleteShader(mVertexShader); mFunctionsGL->deleteShader(mFragmentShader); mFunctionsGL->deleteBuffers(1, &mVertexBuffer); mFunctionsGL->deleteBuffers(1, &mIndexBuffer); mProgram = 0; } DisplayGL::terminate(); if (mContext) { // Mesa might crash if you terminate EGL with a context current // then re-initialize EGL, so make our context not current. mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT); mEGL->destroyContext(mContext); mContext = nullptr; } SafeDelete(mFunctionsGL); if (mEGL) { mEGL->terminate(); SafeDelete(mEGL); } drmModeFreeCrtc(mCRTC); if (mGBM) { int fd = gbm_device_get_fd(mGBM); gbm_device_destroy(mGBM); mGBM = nullptr; close(fd); } }
void DisplayOzone::Buffer::reset() { if (mHasDRMFB) { int fd = gbm_device_get_fd(mDisplay->mGBM); drmModeRmFB(fd, mDRMFB); mHasDRMFB = false; } FunctionsGL *gl = mDisplay->mFunctionsGL; gl->deleteRenderbuffers(1, &mColorBuffer); mColorBuffer = 0; gl->deleteRenderbuffers(1, &mDSBuffer); mDSBuffer = 0; // Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer, // it does not get destroyed (and recreated) because when it is the default framebuffer for // an ANGLE surface then ANGLE expects it to have the same lifetime as that surface. if (mImage != EGL_NO_IMAGE_KHR) { mDisplay->mEGL->destroyImageKHR(mImage); mImage = EGL_NO_IMAGE_KHR; } if (mTexture) { gl->deleteTextures(1, &mTexture); mTexture = 0; } if (mDMABuf >= 0) { close(mDMABuf); mDMABuf = -1; } if (mBO) { gbm_bo_destroy(mBO); mBO = nullptr; } }
uint32_t DisplayOzone::Buffer::getDRMFB() { if (!mHasDRMFB) { int fd = gbm_device_get_fd(mDisplay->mGBM); uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32}; uint32_t pitches[4] = {gbm_bo_get_stride(mBO)}; uint32_t offsets[4] = {0}; if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0)) { std::cerr << "drmModeAddFB2 failed" << std::endl; } else { mHasDRMFB = true; } } return mDRMFB; }
EGLBoolean dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; struct gbm_device *gbm; int fd = -1; int i; dri2_dpy = malloc(sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); memset(dri2_dpy, 0, sizeof *dri2_dpy); disp->DriverData = (void *) dri2_dpy; gbm = disp->PlatformDisplay; if (gbm == NULL) { fd = open("/dev/dri/card0", O_RDWR); dri2_dpy->own_device = 1; gbm = gbm_create_device(fd); if (gbm == NULL) return EGL_FALSE; } if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) { free(dri2_dpy); return EGL_FALSE; } dri2_dpy->gbm_dri = gbm_dri_device(gbm); if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) { free(dri2_dpy); return EGL_FALSE; } if (fd < 0) { fd = dup(gbm_device_get_fd(gbm)); if (fd < 0) { free(dri2_dpy); return EGL_FALSE; } } dri2_dpy->fd = fd; dri2_dpy->device_name = dri2_get_device_name_for_fd(dri2_dpy->fd); dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name; dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen; dri2_dpy->core = dri2_dpy->gbm_dri->core; dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2; dri2_dpy->image = dri2_dpy->gbm_dri->image; dri2_dpy->flush = dri2_dpy->gbm_dri->flush; dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs; dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; dri2_dpy->gbm_dri->lookup_user_data = disp; dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers; dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer; dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format; dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer; dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer; dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers; dri2_setup_screen(disp); for (i = 0; dri2_dpy->driver_configs[i]; i++) dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, EGL_WINDOW_BIT, NULL, NULL); drv->API.CreateWindowSurface = dri2_create_window_surface; drv->API.DestroySurface = dri2_destroy_surface; drv->API.SwapBuffers = dri2_swap_buffers; drv->API.CreateImageKHR = dri2_drm_create_image_khr; #ifdef HAVE_WAYLAND_PLATFORM disp->Extensions.WL_bind_wayland_display = EGL_TRUE; #endif dri2_dpy->authenticate = dri2_drm_authenticate; /* we're supporting EGL 1.4 */ disp->VersionMajor = 1; disp->VersionMinor = 4; return EGL_TRUE; }
EGLBoolean dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; struct gbm_device *gbm; int fd = -1; int i; loader_set_logger(_eglLog); dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); disp->DriverData = (void *) dri2_dpy; gbm = disp->PlatformDisplay; if (gbm == NULL) { char buf[64]; int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0); if (n != -1 && n < sizeof(buf)) fd = open(buf, O_RDWR); if (fd < 0) fd = open("/dev/dri/card0", O_RDWR); dri2_dpy->own_device = 1; gbm = gbm_create_device(fd); if (gbm == NULL) return EGL_FALSE; } if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) { free(dri2_dpy); return EGL_FALSE; } dri2_dpy->gbm_dri = gbm_dri_device(gbm); if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) { free(dri2_dpy); return EGL_FALSE; } if (fd < 0) { fd = dup(gbm_device_get_fd(gbm)); if (fd < 0) { free(dri2_dpy); return EGL_FALSE; } } dri2_dpy->fd = fd; dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->base.driver_name); dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen; dri2_dpy->core = dri2_dpy->gbm_dri->core; dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2; dri2_dpy->image = dri2_dpy->gbm_dri->image; dri2_dpy->flush = dri2_dpy->gbm_dri->flush; dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast; dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs; dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; dri2_dpy->gbm_dri->lookup_user_data = disp; dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers; dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer; dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format; dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers; dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2; dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image; dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer; dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer; dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers; dri2_setup_screen(disp); for (i = 0; dri2_dpy->driver_configs[i]; i++) { EGLint format, attr_list[3]; unsigned int mask; dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], __DRI_ATTRIB_RED_MASK, &mask); if (mask == 0x3ff00000) format = GBM_FORMAT_XRGB2101010; else if (mask == 0x00ff0000) format = GBM_FORMAT_XRGB8888; else if (mask == 0xf800) format = GBM_FORMAT_RGB565; else continue; attr_list[0] = EGL_NATIVE_VISUAL_ID; attr_list[1] = format; attr_list[2] = EGL_NONE; dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, EGL_WINDOW_BIT, attr_list, NULL); } if (dri2_dpy->dri2) disp->Extensions.EXT_buffer_age = EGL_TRUE; #ifdef HAVE_WAYLAND_PLATFORM if (dri2_dpy->image) { if (dri2_dpy->image->base.version >= 10 && dri2_dpy->image->getCapabilities != NULL) { int capabilities; capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); disp->Extensions.WL_bind_wayland_display = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; } else disp->Extensions.WL_bind_wayland_display = EGL_TRUE; } #endif /* we're supporting EGL 1.4 */ disp->VersionMajor = 1; disp->VersionMinor = 4; /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */ dri2_dpy->vtbl = &dri2_drm_display_vtbl; return EGL_TRUE; }
uint32_t update_buffer_nativesurface(struct ivi_share_nativesurface *p_nativesurface) { if (NULL == p_nativesurface || NULL == p_nativesurface->surface) { return IVI_SHAREBUFFER_NOT_AVAILABLE; } struct drm_backend *backend = (struct drm_backend*)p_nativesurface->surface->compositor->backend; if (NULL == backend) { return IVI_SHAREBUFFER_NOT_AVAILABLE; } struct weston_buffer *buffer = p_nativesurface->surface->buffer_ref.buffer; if (!buffer) { return IVI_SHAREBUFFER_NOT_AVAILABLE; } struct gbm_bo *bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_WL_BUFFER, buffer->legacy_buffer, GBM_BO_USE_SCANOUT); if (!bo) { weston_log("failed to import gbm_bo\n"); return IVI_SHAREBUFFER_INVALID; } struct drm_gem_flink flink = {0}; flink.handle = gbm_bo_get_handle(bo).u32; if (drmIoctl(gbm_device_get_fd(backend->gbm), DRM_IOCTL_GEM_FLINK, &flink) != 0) { weston_log("gem_flink: returned non-zero failed\n"); gbm_bo_destroy(bo); return IVI_SHAREBUFFER_INVALID; } uint32_t name = flink.name; uint32_t width = gbm_bo_get_width(bo); uint32_t height = gbm_bo_get_height(bo); uint32_t stride = gbm_bo_get_stride(bo); uint32_t format = IVI_SHARE_SURFACE_FORMAT_ARGB8888; uint32_t ret = IVI_SHAREBUFFER_STABLE; if (name != p_nativesurface->name) { ret |= IVI_SHAREBUFFER_DAMAGE; } if (width != p_nativesurface->width) { ret |= IVI_SHAREBUFFER_CONFIGURE; } if (height != p_nativesurface->height) { ret |= IVI_SHAREBUFFER_CONFIGURE; } if (stride != p_nativesurface->stride) { ret |= IVI_SHAREBUFFER_CONFIGURE; } p_nativesurface->name = name; p_nativesurface->width = width; p_nativesurface->height = height; p_nativesurface->stride = stride; p_nativesurface->format = format; gbm_bo_destroy(bo); return ret; }