static cairo_surface_t * display_create_drm_surface(struct display *display, struct rectangle *rectangle) { struct drm_surface_data *data; EGLDisplay dpy = display->dpy; cairo_surface_t *surface; struct wl_visual *visual; EGLint name, stride; EGLint image_attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; data = malloc(sizeof *data); if (data == NULL) return NULL; data->display = display; image_attribs[1] = rectangle->width; image_attribs[3] = rectangle->height; data->image = eglCreateDRMImageMESA(dpy, image_attribs); cairo_device_acquire(display->device); glGenTextures(1, &data->texture); glBindTexture(GL_TEXTURE_2D, data->texture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, data->image); cairo_device_release(display->device); eglExportDRMImageMESA(display->dpy, data->image, &name, NULL, &stride); visual = wl_display_get_premultiplied_argb_visual(display->display); data->data.buffer = wl_drm_create_buffer(display->drm, name, rectangle->width, rectangle->height, stride, visual); surface = cairo_gl_surface_create_for_texture(display->device, CAIRO_CONTENT_COLOR_ALPHA, data->texture, rectangle->width, rectangle->height); cairo_surface_set_user_data (surface, &surface_data_key, data, drm_surface_data_destroy); return surface; }
static struct wl_buffer * wayland_create_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); struct wl_buffer *buf; buf = wl_drm_create_buffer(dri2_dpy->wl_drm, buffer->name, dri2_surf->base.Width, dri2_surf->base.Height, buffer->pitch, dri2_surf->format); wl_buffer_add_listener(buf, &wl_buffer_listener, dri2_surf); return buf; }
static ClutterStageWaylandWaylandBuffer * wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland, ClutterGeometry *geom) { EGLDisplay edpy = clutter_wayland_get_egl_display (); struct wl_visual *visual; EGLint name, stride; ClutterStageWaylandWaylandBufferDRM *buffer; EGLint image_attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; buffer = g_slice_new (ClutterStageWaylandWaylandBufferDRM); buffer->buffer.type = BUFFER_TYPE_DRM; image_attribs[1] = geom->width; image_attribs[3] = geom->height; buffer->drm_image = backend_wayland->create_drm_image (edpy, image_attribs); glGenTextures (1, &buffer->texture); glBindTexture (GL_TEXTURE_2D, buffer->texture); backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image); buffer->buffer.tex = cogl_texture_new_from_foreign (buffer->texture, GL_TEXTURE_2D, geom->width, geom->height, 0, 0, VISUAL_ARGB_PRE); backend_wayland->export_drm_image (edpy, buffer->drm_image, &name, NULL, &stride); visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); buffer->buffer.wayland_buffer = wl_drm_create_buffer (backend_wayland->wayland_drm, name, geom->width, geom->height, stride, visual); return &buffer->buffer; }
/** * Called via eglCreateImageKHR(), drv->API.CreateImageKHR(). */ 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 wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer; struct dri2_egl_buffer *dri2_buf; EGLint wl_attr_list[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_DRM_BUFFER_STRIDE_MESA, 0, EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, EGL_NONE }; dri2_buf = malloc(sizeof *dri2_buf); if (!dri2_buf) return NULL; dri2_buf->dri2_dpy = dri2_dpy; dri2_buf->dri_buffer = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, __DRI_BUFFER_FRONT_LEFT, 32, wl_egl_pixmap->width, wl_egl_pixmap->height); wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy; wl_egl_pixmap->driver_private = dri2_buf; /* FIXME: Get buffer format from attr_list somehow... or from the wl_egl_piaxmap. */ wl_egl_pixmap->buffer = wl_drm_create_buffer(dri2_dpy->wl_drm, dri2_buf->dri_buffer->name, wl_egl_pixmap->width, wl_egl_pixmap->height, dri2_buf->dri_buffer->pitch, WL_DRM_FORMAT_PREMULTIPLIED_ARGB32); wl_attr_list[1] = wl_egl_pixmap->width; wl_attr_list[3] = wl_egl_pixmap->height; wl_attr_list[5] = dri2_buf->dri_buffer->pitch / 4; return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA, (EGLClientBuffer)(intptr_t) dri2_buf->dri_buffer->name, wl_attr_list); }
static struct wl_buffer * wayland_create_drm_buffer(struct wayland_display *display, struct wayland_surface *surface, enum native_attachment attachment) { struct wayland_drm_display *drmdpy = (struct wayland_drm_display *) display; struct pipe_screen *screen = drmdpy->base.base.screen; struct pipe_resource *resource; struct winsys_handle wsh; uint width, height; enum wl_drm_format format; resource = resource_surface_get_single_resource(surface->rsurf, attachment); resource_surface_get_size(surface->rsurf, &width, &height); wsh.type = DRM_API_HANDLE_TYPE_SHARED; screen->resource_get_handle(screen, resource, &wsh); pipe_resource_reference(&resource, NULL); switch (surface->color_format) { case PIPE_FORMAT_B8G8R8A8_UNORM: format = (surface->premultiplied_alpha) ? WL_DRM_FORMAT_PREMULTIPLIED_ARGB32 : WL_DRM_FORMAT_ARGB32; break; case PIPE_FORMAT_B8G8R8X8_UNORM: format = WL_DRM_FORMAT_XRGB32; break; default: return NULL; break; } return wl_drm_create_buffer(drmdpy->wl_drm, wsh.handle, width, height, wsh.stride, format); }
/* Create the WSEGL drawable version of a native window */ static WSEGLError wseglCreateWindowDrawable (WSEGLDisplayHandle display, WSEGLConfig *config, WSEGLDrawableHandle *drawable, NativeWindowType nativeWindow, WSEGLRotationAngle *rotationAngle) { struct wl_egl_display *egldisplay = (struct wl_egl_display *) display; int index; /* Framebuffer */ if (nativeWindow == NULL) { PVR2DDISPLAYINFO displayInfo; assert(egldisplay->display == NULL); /* Let's create a fake wl_egl_window to simplify code */ nativeWindow = wl_egl_window_create(NULL, egldisplay->var.xres, egldisplay->var.yres); nativeWindow->format = getwseglPixelFormat(egldisplay); nativeWindow->display = egldisplay; assert(PVR2DGetDeviceInfo(egldisplay->context, &displayInfo) == PVR2D_OK); if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0) nativeWindow->numFlipBuffers = displayInfo.ulMaxBuffersInChain; if (nativeWindow->numFlipBuffers > WAYLANDWSEGL_MAX_FLIP_BUFFERS) nativeWindow->numFlipBuffers = WAYLANDWSEGL_MAX_FLIP_BUFFERS; /* Workaround for broken devices, seen in debugging */ if (nativeWindow->numFlipBuffers < 2) nativeWindow->numFlipBuffers = 0; } else { nativeWindow->display = egldisplay; nativeWindow->format = WSEGL_PIXELFORMAT_8888; } /* We can't do empty buffers, so let's make a 8x8 one. */ if (nativeWindow->width == 0 || nativeWindow->height == 0) { nativeWindow->width = nativeWindow->height = 8; } /* If we don't have back buffers allocated already */ if (!(nativeWindow->backBuffers[0] && nativeWindow->backBuffersValid)) { nativeWindow->stridePixels = (nativeWindow->width + 7) & ~7; nativeWindow->strideBytes = nativeWindow->stridePixels * wseglPixelFormatBytesPP(nativeWindow->format); if (allocateBackBuffers(egldisplay, nativeWindow) == WSEGL_OUT_OF_MEMORY) return WSEGL_OUT_OF_MEMORY; /* Wayland window */ if (nativeWindow->display->display != NULL) { for (index = 0; index < WAYLANDWSEGL_MAX_BACK_BUFFERS; index++) { PVR2D_HANDLE name; assert(PVR2DMemExport(egldisplay->context, 0, nativeWindow->backBuffers[index], &name) == PVR2D_OK); nativeWindow->drmbuffers[index] = wl_drm_create_buffer(egldisplay->drm, (uint32_t)name, nativeWindow->width, nativeWindow->height, nativeWindow->strideBytes, nativeWindow->format); assert(nativeWindow->drmbuffers[index] != NULL); } } /* Framebuffer */ else { assert(PVR2DGetFrameBuffer(egldisplay->context, PVR2D_FB_PRIMARY_SURFACE, &nativeWindow->frontBufferPVRMEM) == PVR2D_OK); } } *drawable = (WSEGLDrawableHandle) nativeWindow; /* Reuse the egldisplay */ *rotationAngle = WSEGL_ROTATE_0; return WSEGL_SUCCESS; }