static Bool _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits, Bool fallback) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); RegionPtr clip; int x_off, y_off; Bool ret = FALSE; PixmapPtr temp_pixmap, sub_pixmap; glamor_pixmap_private *temp_pixmap_priv; BoxRec box; int stride; glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); clip = fbGetCompositeClip(gc); if (image_format == XYBitmap) { assert(depth == 1); goto fail; } if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("has no fbo.\n"); goto fail; } if (image_format != ZPixmap) { glamor_fallback("non-ZPixmap\n"); goto fail; } if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } /* create a temporary pixmap and upload the bits to that * pixmap, then apply clip copy it to the destination pixmap.*/ stride = PixmapBytePad(w, depth); box.x1 = x + drawable->x; box.y1 = y + drawable->y; box.x2 = x + w + drawable->x; box.y2 = y + h + drawable->y; if ((clip != NULL && RegionContainsRect(clip, &box) != rgnIN) || gc->alu != GXcopy) { temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); if (temp_pixmap == NULL) goto fail; temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { temp_pixmap_priv->base.picture = pixmap_priv->base.picture; temp_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, stride, bits, 0); glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y); glamor_destroy_pixmap(temp_pixmap); } else { glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off, y + drawable->y + y_off, w, h, stride, bits, 0); } ret = TRUE; goto done; fail: glamor_set_planemask(pixmap, ~0); if (!fallback && glamor_ddx_fallback_check_pixmap(&pixmap->drawable)) goto done; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x, y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RW); if (sub_pixmap) { if (clip != NULL) pixman_region_translate (clip, -x - drawable->x, -y - drawable->y); fbPutImage(&sub_pixmap->drawable, gc, depth, 0, 0, w, h, left_pad, image_format, bits); glamor_put_sub_pixmap(sub_pixmap, pixmap, x + x_off + drawable->x, y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RW); if (clip != NULL) pixman_region_translate (clip, x + drawable->x, y + drawable->y); } else fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); ret = TRUE; done: return ret; }
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; }
static void glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { ScreenPtr screen = drawable->pScreen; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); float fg[4], bg[4]; GLuint tex; unsigned int stride = PixmapBytePad(1, w + left_pad); RegionPtr clip; BoxPtr box; int nbox; float dest_coords[8]; const float bitmap_coords[8] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, }; GLfloat xscale, yscale; glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x, y, x + w, y + h, glamor_priv->yInverted, dest_coords); glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; if (glamor_priv->put_image_xybitmap_prog == 0) { ErrorF("no program for xybitmap putimage\n"); goto fail; } glamor_set_alu(gc->alu); if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); /* Now that we've set up our bitmap texture and the shader, shove * the destination rectangle through the cliprects and run the * shader on the resulting fragments. */ dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); dispatch->glEnableClientState(GL_VERTEX_ARRAY); dispatch->glClientActiveTexture(GL_TEXTURE0); dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); dispatch->glEnable(GL_SCISSOR_TEST); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nbox--; box++) { int x1 = x; int y1 = y; int x2 = x + w; int y2 = y + h; if (x1 < box->x1) x1 = box->x1; if (y1 < box->y1) y1 = box->y1; if (x2 > box->x2) x2 = box->x2; if (y2 > box->y2) y2 = box->y2; if (x1 >= x2 || y1 >= y2) continue; dispatch->glScissor(box->x1, y_flip(pixmap, box->y1), box->x2 - box->x1, box->y2 - box->y1); dispatch->glDrawArrays(GL_QUADS, 0, 4); } dispatch->glDisable(GL_SCISSOR_TEST); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); dispatch->glDeleteTextures(1, &tex); dispatch->glDisableClientState(GL_VERTEX_ARRAY); dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); return; glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); glamor_fallback(": to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); fail: if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); } glamor_finish_access_gc(gc); glamor_finish_access(drawable); }
static Bool _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int numPoints, int sorted, Bool fallback) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *dest_pixmap_priv; int i; uint8_t *drawpixels_src = (uint8_t *) src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; Bool ret = FALSE; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; } /* XXX Shall we set alu here? */ if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); for (i = 0; i < numPoints; i++) { int n = REGION_NUM_RECTS(clip); pbox = REGION_RECTS(clip); while (n--) { int x1 = points[i].x; int x2 = x1 + widths[i]; int y1 = points[i].y; if (pbox->y1 > points[i].y || pbox->y2 < points[i].y) break; x1 = x1 > pbox->x1 ? x1 : pbox->x1; x2 = x2 < pbox->x2 ? x2 : pbox->x2; if (x1 >= x2) continue; glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, y1 + y_off, x2 - x1, 1, PixmapBytePad(widths[i], drawable->depth), drawpixels_src, 0); } drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } ret = TRUE; goto done; fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) goto done; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } ret = TRUE; done: return ret; }