Bool glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; GLuint texture; Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); glamor_get_context(glamor_priv); image = eglCreateImageKHR(glamor_egl->display, glamor_egl->context, EGL_NATIVE_PIXMAP_KHR, bo, NULL); if (image == EGL_NO_IMAGE_KHR) { glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; } glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); ret = TRUE; done: glamor_put_context(glamor_priv); return ret; }
/* * We should already have drawable attached to it, if it has one. * Then set the attached pixmap to is_picture format, and set * the pict format. * */ int glamor_create_picture(PicturePtr picture) { PixmapPtr pixmap; glamor_pixmap_private *pixmap_priv; if (!picture || !picture->pDrawable) return 0; pixmap = glamor_get_drawable_pixmap(picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); if (!pixmap_priv) { /* We must create a pixmap priv to track the picture format even * if the pixmap is a pure in memory pixmap. The reason is that * we may need to upload this pixmap to a texture on the fly. During * the uploading, we need to know the picture format. */ glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); pixmap_priv = glamor_get_pixmap_private(pixmap); } else { if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* If the picture format is not compatible with glamor fbo format, * we have to mark this pixmap as a separated texture, and don't * fallback to DDX layer. */ if (pixmap_priv->type == GLAMOR_TEXTURE_DRM && !glamor_pict_format_is_compatible(picture)) glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); } } pixmap_priv->base.is_picture = 1; pixmap_priv->base.picture = picture; return miCreatePicture(picture); }
Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; GLuint texture; int name; Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); glamor_get_context(glamor_priv); if (glamor_egl->has_gem) { if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); assert(0); return FALSE; } } else name = handle; image = _glamor_egl_create_image(glamor_egl, pixmap->drawable.width, pixmap->drawable.height, ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), name, pixmap->drawable.depth); if (image == EGL_NO_IMAGE_KHR) { glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; } glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); ret = TRUE; done: glamor_put_context(glamor_priv); return ret; }
_X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) { ScrnInfoPtr scrn = xf86ScreenToScrn(front->drawable.pScreen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); EGLImageKHR old_front_image; EGLImageKHR new_front_image; glamor_pixmap_exchange_fbos(front, back); new_front_image = dixLookupPrivate(&back->devPrivates, glamor_egl_pixmap_private_key); old_front_image = dixLookupPrivate(&front->devPrivates, glamor_egl_pixmap_private_key); dixSetPrivate(&front->devPrivates, glamor_egl_pixmap_private_key, new_front_image); dixSetPrivate(&back->devPrivates, glamor_egl_pixmap_private_key, old_front_image); glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); glamor_egl->front_image = new_front_image; }
static PixmapPtr xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth) { PixmapPtr pixmap; struct xwl_pixmap *xwl_pixmap; struct xwl_screen *xwl_screen = xwl_screen_get(screen); xwl_pixmap = malloc(sizeof *xwl_pixmap); if (xwl_pixmap == NULL) return NULL; pixmap = glamor_create_pixmap(screen, gbm_bo_get_width(bo), gbm_bo_get_height(bo), depth, GLAMOR_CREATE_PIXMAP_NO_TEXTURE); if (pixmap == NULL) { free(xwl_pixmap); return NULL; } if (lastGLContext != xwl_screen->glamor_ctx) { lastGLContext = xwl_screen->glamor_ctx; xwl_glamor_egl_make_current(xwl_screen->glamor_ctx); } xwl_pixmap->bo = bo; xwl_pixmap->buffer = NULL; xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display, xwl_screen->egl_context, EGL_NATIVE_PIXMAP_KHR, xwl_pixmap->bo, NULL); glGenTextures(1, &xwl_pixmap->texture); glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image); glBindTexture(GL_TEXTURE_2D, 0); xwl_pixmap_set_private(pixmap, xwl_pixmap); glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); return pixmap; }
static Bool _glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure, Bool fallback) { PixmapPtr dst_pixmap, src_pixmap; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; BoxPtr extent; RegionRec region; int src_x_off, src_y_off, dst_x_off, dst_y_off; Bool ok = FALSE; int force_clip = 0; if (nbox == 0) return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); glamor_priv = glamor_get_screen_private(dst->pScreen); DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", box[0].x1, box[0].y1, box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, dx, dy, src_pixmap, dst_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) goto fall_back; if (gc) { if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fall_back; dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { glamor_put_dispatch(glamor_priv); goto fail_noregion; } glamor_put_dispatch(glamor_priv); } if (!src_pixmap_priv) { glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); } glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); RegionInitBoxes(®ion, box, nbox); extent = RegionExtents(®ion); if (!glamor_check_fbo_size(glamor_priv, extent->x2 - extent->x1, extent->y2 - extent->y1) && (src_pixmap_priv->type == GLAMOR_MEMORY || (src_pixmap_priv == dst_pixmap_priv))) { force_clip = 1; } if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { glamor_pixmap_clipped_regions *clipped_dst_regions; int n_dst_region, i, j; PixmapPtr temp_source_pixmap; glamor_pixmap_private *temp_source_priv = NULL; RegionTranslate(®ion, dst_x_off, dst_y_off); if (!force_clip) clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, ®ion, &n_dst_region, 0, reverse, upsidedown); else clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, &n_dst_region, glamor_priv->max_fbo_size, glamor_priv->max_fbo_size, reverse, upsidedown); for(i = 0; i < n_dst_region; i++) { int n_src_region; glamor_pixmap_clipped_regions *clipped_src_regions; BoxPtr current_boxes; int n_current_boxes; SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx); temp_source_pixmap = NULL; if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionTranslate(clipped_dst_regions[i].region, -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, &n_src_region, 0, reverse, upsidedown); DEBUGF("Source is large pixmap.\n"); for (j = 0; j < n_src_region; j++) { if (src_pixmap_priv != dst_pixmap_priv) SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); else if (src_pixmap_priv == dst_pixmap_priv && clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx) { /* source and the dest are the same, but need different block_idx. * we create a empty pixmap and fill the required source fbo and box to * it. It's a little hacky, but avoid extra copy. */ temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0, src->depth, 0); if (!temp_source_pixmap) { ok = FALSE; goto fail; } src->pScreen->ModifyPixmapHeader(temp_source_pixmap, src_pixmap->drawable.width, src_pixmap->drawable.height, 0, 0, src_pixmap->devKind, NULL); temp_source_priv = glamor_get_pixmap_private(temp_source_pixmap); *temp_source_priv = *src_pixmap_priv; temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.pixmap = temp_source_pixmap; } assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); RegionTranslate(clipped_src_regions[j].region, -src_x_off - dx, -src_y_off - dy); current_boxes = RegionRects(clipped_src_regions[j].region); n_current_boxes = RegionNumRects(clipped_src_regions[j].region); DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx, clipped_src_regions[j].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); if (!temp_source_pixmap) ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); else { ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->base.fbo = NULL; glamor_destroy_pixmap(temp_source_pixmap); temp_source_pixmap = NULL; } RegionDestroy(clipped_src_regions[j].region); if (!ok) { assert(0); goto fail; } } if (n_src_region == 0) ok = TRUE; free(clipped_src_regions); } else { RegionTranslate(clipped_dst_regions[i].region, - dst_x_off, - dst_y_off); current_boxes = RegionRects(clipped_dst_regions[i].region); n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); DEBUGF("dest pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); } RegionDestroy(clipped_dst_regions[i].region); } if (n_dst_region == 0) ok = TRUE; free(clipped_dst_regions); } else { ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } fail: RegionUninit(®ion); fail_noregion: dispatch = glamor_get_dispatch(glamor_priv); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); if (ok) return TRUE; fall_back: if (!fallback && glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) goto done; if (src_pixmap_priv->type == GLAMOR_DRM_ONLY || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { LogMessage(X_WARNING, "Access a DRM only pixmap is not allowed within glamor.\n"); return TRUE; } glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO) && glamor_prepare_access_gc(gc)) { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } glamor_finish_access_gc(gc); glamor_finish_access(src); glamor_finish_access(dst); ok = TRUE; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); return ok; }
int glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, PixmapPtr pixmap, unsigned int tex, Bool want_name, CARD16 *stride, CARD32 *size) { #ifdef GLAMOR_HAS_GBM ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; struct gbm_bo *bo; int fd = -1; EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; glamor_egl = glamor_egl_get_screen_private(scrn); glamor_get_context(glamor_priv); image = dixLookupPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key); if (image == EGL_NO_IMAGE_KHR || image == NULL) { image = eglCreateImageKHR(glamor_egl->display, glamor_egl->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (uintptr_t) tex, attribs); if (image == EGL_NO_IMAGE_KHR) goto failure; dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); } bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); if (!bo) goto failure; pixmap->devKind = gbm_bo_get_stride(bo); if (want_name) { if (glamor_egl->has_gem) glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); } else { if (glamor_get_fd_from_bo(glamor_egl->fd, bo, &fd)) { *stride = pixmap->devKind; *size = pixmap->devKind * gbm_bo_get_height(bo); } } gbm_bo_destroy(bo); failure: glamor_put_context(glamor_priv); return fd; #else return -1; #endif }