static void glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *prog, struct glamor_glyph_atlas *atlas, int nglyph) { DrawablePtr drawable = dst->pDrawable; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); PixmapPtr atlas_pixmap = atlas->atlas; glamor_pixmap_private *atlas_priv = glamor_get_pixmap_private(atlas_pixmap); glamor_pixmap_fbo *atlas_fbo = glamor_pixmap_fbo_at(atlas_priv, 0, 0); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int box_x, box_y; int off_x, off_y; glamor_put_vbo_space(drawable->pScreen); glEnable(GL_SCISSOR_TEST); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, atlas_fbo->tex); for (;;) { if (!glamor_use_program_render(prog, op, src, dst)) break; glUniform1i(prog->atlas_uniform, 1); glamor_pixmap_loop(pixmap_priv, box_x, box_y) { BoxPtr box = RegionRects(dst->pCompositeClip); int nbox = RegionNumRects(dst->pCompositeClip); glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); /* Run over the clip list, drawing the glyphs * in each box */ while (nbox--) { glScissor(box->x1 + off_x, box->y1 + off_y, box->x2 - box->x1, box->y2 - box->y1); box++; if (glamor_glyph_use_130(glamor_priv)) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); else glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph); } } if (prog->alpha != glamor_program_alpha_ca_first) break; prog++; }
void glamor_set_destination_drawable(DrawablePtr drawable, int box_index, Bool do_drawable_translate, Bool center_offset, GLint matrix_uniform_location, int *p_off_x, int *p_off_y) { ScreenPtr screen = drawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int off_x, off_y; BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index); int w = box->x2 - box->x1; int h = box->y2 - box->y1; float scale_x = 2.0f / (float) w; float scale_y = 2.0f / (float) h; float center_adjust = 0.0f; glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); off_x -= box->x1; off_y -= box->y1; if (p_off_x) { *p_off_x = off_x; *p_off_y = off_y; } /* A tricky computation to find the right value for the two linear functions * that transform rendering coordinates to pixmap coordinates * * pixmap_x = render_x + drawable->x + off_x * pixmap_y = render_y + drawable->y + off_y * * gl_x = pixmap_x * 2 / width - 1 * gl_y = pixmap_y * 2 / height - 1 * * gl_x = (render_x + drawable->x + off_x) * 2 / width - 1 * * gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1 */ if (do_drawable_translate) { off_x += drawable->x; off_y += drawable->y; } /* * To get GL_POINTS drawn in the right spot, we need to adjust the * coordinates by 1/2 a pixel. */ if (center_offset) center_adjust = 0.5f; glUniform4f(matrix_uniform_location, scale_x, (off_x + center_adjust) * scale_x - 1.0f, scale_y, (off_y + center_adjust) * scale_y - 1.0f); glamor_set_destination_pixmap_fbo(glamor_priv, glamor_pixmap_fbo_at(pixmap_priv, box_index), 0, 0, w, h); }
static Bool glamor_copy_fbo_fbo_draw(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { ScreenPtr screen = dst->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap); int src_box_index, dst_box_index; int dst_off_x, dst_off_y; int src_off_x, src_off_y; GLshort *v; char *vbo_offset; struct copy_args args; glamor_program *prog; const glamor_facet *copy_facet; int n; glamor_make_current(glamor_priv); if (gc && !glamor_set_planemask(gc->depth, gc->planemask)) goto bail_ctx; if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) goto bail_ctx; if (bitplane) { prog = &glamor_priv->copy_plane_prog; copy_facet = &glamor_facet_copyplane; } else { prog = &glamor_priv->copy_area_prog; copy_facet = &glamor_facet_copyarea; } if (prog->failed) goto bail_ctx; if (!prog->prog) { if (!glamor_build_program(screen, prog, copy_facet, NULL, NULL, NULL)) goto bail_ctx; } args.src_pixmap = src_pixmap; args.bitplane = bitplane; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 2 * sizeof (GLshort), vbo_offset); for (n = 0; n < nbox; n++) { v[0] = box->x1; v[1] = box->y1; v[2] = box->x1; v[3] = box->y2; v[4] = box->x2; v[5] = box->y2; v[6] = box->x2; v[7] = box->y1; v += 8; box++; } glamor_put_vbo_space(screen); glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(src_priv, src_box_index) { BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_index); args.dx = dx + src_off_x - src_box->x1; args.dy = dy + src_off_y - src_box->y1; args.src = glamor_pixmap_fbo_at(src_priv, src_box_index); if (!glamor_use_program(dst_pixmap, gc, prog, &args)) goto bail_ctx; glamor_pixmap_loop(dst_priv, dst_box_index) { glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE, prog->matrix_uniform, &dst_off_x, &dst_off_y); glScissor(dst_off_x - args.dx, dst_off_y - args.dy, src_box->x2 - src_box->x1, src_box->y2 - src_box->y1); glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox); }
/* * Write a region of bits into a pixmap */ void glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, int dx_src, int dy_src, int dx_dst, int dy_dst, uint8_t *bits, uint32_t byte_stride) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); int box_index; int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; GLenum type; GLenum format; glamor_format_for_pixmap(pixmap, &format, &type); glamor_make_current(glamor_priv); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (glamor_priv->has_unpack_subimage) glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel); glamor_pixmap_loop(priv, box_index) { BoxPtr box = glamor_pixmap_box_at(priv, box_index); glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_index); BoxPtr boxes = in_boxes; int nbox = in_nbox; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fbo->tex); while (nbox--) { /* compute drawable coordinates */ int x1 = MAX(boxes->x1 + dx_dst, box->x1); int x2 = MIN(boxes->x2 + dx_dst, box->x2); int y1 = MAX(boxes->y1 + dy_dst, box->y1); int y2 = MIN(boxes->y2 + dy_dst, box->y2); size_t ofs = (y1 - dy_dst + dy_src) * byte_stride; ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel; boxes++; if (x2 <= x1 || y2 <= y1) continue; if (glamor_priv->has_unpack_subimage || x2 - x1 == byte_stride / bytes_per_pixel) { glTexSubImage2D(GL_TEXTURE_2D, 0, x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs); } else { for (; y1 < y2; y1++, ofs += byte_stride) glTexSubImage2D(GL_TEXTURE_2D, 0, x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs); } } }