QDri2Context::QDri2Context(QXcbWindow *window) : d_ptr(new QDri2ContextPrivate(window)) { Q_D(QDri2Context); static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; eglBindAPI(EGL_OPENGL_ES_API); EGLContext shareContext = EGL_NO_CONTEXT; if (window->widget()->platformWindowFormat().sharedGLContext()) { QDri2Context *context = static_cast<QDri2Context *>(window->widget()->platformWindowFormat().sharedGLContext()); shareContext = context->d_func()->eglContext; } d->eglContext = eglCreateContext(EGL_DISPLAY_FROM_XCB(d->qXcbWindow), NULL, shareContext, contextAttribs); if (d->eglContext == EGL_NO_CONTEXT) { qDebug() << "No eglContext!" << eglGetError(); } EGLBoolean makeCurrentSuccess = eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,d->eglContext); if (!makeCurrentSuccess) { qDebug() << "eglMakeCurrent failed!" << eglGetError(); } xcb_dri2_create_drawable (d->xcbConnection(), d->xcbWindow()); glGenFramebuffers(1,&d->fbo); glBindFramebuffer(GL_FRAMEBUFFER,d->fbo); glActiveTexture(GL_TEXTURE0); glGenRenderbuffers(1, &d->rbo); glBindRenderbuffer(GL_RENDERBUFFER, d->rbo); glGenRenderbuffers(1,&d->depth); glBindRenderbuffer(GL_RENDERBUFFER, d->depth); resize(d->qXcbWindow->widget()->geometry().size()); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, d->rbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERER,d->depth); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERER,d->depth); //restore the old current context const QPlatformGLContext *currentContext = QPlatformGLContext::currentContext(); if (currentContext) const_cast<QPlatformGLContext*>(currentContext)->makeCurrent(); }
static cairo_surface_t * _xcb_drm_create_surface_for_drawable (cairo_xcb_connection_t *connection, cairo_xcb_screen_t *screen, xcb_drawable_t drawable, pixman_format_code_t pixman_format, int width, int height) { uint32_t attachments[] = { XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT }; xcb_dri2_get_buffers_reply_t *buffers; xcb_dri2_dri2_buffer_t *buffer; cairo_surface_t *surface; if (! _cairo_drm_size_is_valid (screen->device, width, height)) return NULL; xcb_dri2_create_drawable (connection->xcb_connection, drawable); buffers = xcb_dri2_get_buffers_reply (connection->xcb_connection, xcb_dri2_get_buffers (connection->xcb_connection, drawable, 1, ARRAY_LENGTH (attachments), attachments), 0); if (buffers == NULL) { xcb_dri2_destroy_drawable (connection->xcb_connection, drawable); return NULL; } /* If the drawable is a window, we expect to receive an extra fake front, * which would involve copying on each flush - contrary to the user * expectations. But that is likely to be preferable to mixing drm/xcb * operations. */ buffer = xcb_dri2_get_buffers_buffers (buffers); if (buffers->count == 1 && buffer[0].attachment == XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT) { assert (buffer[0].cpp == PIXMAN_FORMAT_BPP (pixman_format) / 8); surface = cairo_drm_surface_create_for_name (screen->device, buffer[0].name, _cairo_format_from_pixman_format (pixman_format), width, height, buffer[0].pitch); } else { xcb_dri2_destroy_drawable (connection->xcb_connection, drawable); surface = NULL; } free (buffers); return surface; }
static void vl_dri2_set_drawable(struct vl_dri_screen *scrn, Drawable drawable) { assert(scrn); assert(drawable); if (scrn->drawable == drawable) return; vl_dri2_destroy_drawable(scrn); xcb_dri2_create_drawable(scrn->conn, drawable); scrn->current_buffer = false; vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); scrn->drawable = drawable; }
static _EGLImage * dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer buffer, const EGLint *attr_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_image *dri2_img; unsigned int attachments[1]; xcb_drawable_t drawable; xcb_dri2_get_buffers_cookie_t buffers_cookie; xcb_dri2_get_buffers_reply_t *buffers_reply; xcb_dri2_dri2_buffer_t *buffers; xcb_get_geometry_cookie_t geometry_cookie; xcb_get_geometry_reply_t *geometry_reply; xcb_generic_error_t *error; int stride, format; (void) ctx; drawable = (xcb_drawable_t) (uintptr_t) buffer; xcb_dri2_create_drawable (dri2_dpy->conn, drawable); attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; buffers_cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, drawable, 1, 1, attachments); geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, buffers_cookie, NULL); buffers = xcb_dri2_get_buffers_buffers (buffers_reply); if (buffers == NULL) { return NULL; } geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, geometry_cookie, &error); if (geometry_reply == NULL || error != NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); free(error); free(buffers_reply); return NULL; } switch (geometry_reply->depth) { case 16: format = __DRI_IMAGE_FORMAT_RGB565; break; case 24: format = __DRI_IMAGE_FORMAT_XRGB8888; break; case 32: format = __DRI_IMAGE_FORMAT_ARGB8888; break; default: _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr: unsupported pixmap depth"); free(buffers_reply); free(geometry_reply); return NULL; } dri2_img = malloc(sizeof *dri2_img); if (!dri2_img) { free(buffers_reply); free(geometry_reply); _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); return EGL_NO_IMAGE_KHR; } if (!_eglInitImage(&dri2_img->base, disp)) { free(buffers_reply); free(geometry_reply); free(dri2_img); return EGL_NO_IMAGE_KHR; } stride = buffers[0].pitch / buffers[0].cpp; dri2_img->dri_image = dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, buffers_reply->width, buffers_reply->height, format, buffers[0].name, stride, dri2_img); free(buffers_reply); free(geometry_reply); return &dri2_img->base; }
/** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, EGLNativeWindowType native_window, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_screen_iterator_t s; xcb_generic_error_t *error; xcb_drawable_t window = (uintptr_t )native_window; (void) drv; dri2_surf = malloc(sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) goto cleanup_surf; dri2_surf->region = XCB_NONE; if (type == EGL_PBUFFER_BIT) { dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, dri2_surf->drawable, s.data->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { dri2_surf->drawable = window; } if (dri2_dpy->dri2) { dri2_surf->dri_drawable = (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, type == EGL_WINDOW_BIT ? dri2_conf->dri_double_config : dri2_conf->dri_single_config, dri2_surf); } else { assert(dri2_dpy->swrast); dri2_surf->dri_drawable = (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen, dri2_conf->dri_double_config, dri2_surf); } if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } if (dri2_dpy->dri2) { xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); } else { swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE)); } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); if (reply == NULL || error != NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); free(error); goto cleanup_dri_drawable; } dri2_surf->base.Width = reply->width; dri2_surf->base.Height = reply->height; free(reply); } /* we always copy the back buffer to front */ dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; return &dri2_surf->base; cleanup_dri_drawable: dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); cleanup_pixmap: if (type == EGL_PBUFFER_BIT) xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); cleanup_surf: free(dri2_surf); return NULL; }