static void glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog, int n, GLenum mode) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int box_index; int off_x, off_y; glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(pixmap_priv, box_index) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, box->y1 + off_y, box->x2 - box->x1, box->y2 - box->y1); box++; glDrawArrays(mode, 0, n); } }
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++; }
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); }
static int glamor_text(DrawablePtr drawable, GCPtr gc, glamor_font_t *glamor_font, glamor_program *prog, int x, int y, int count, char *s_chars, CharInfoPtr *charinfo, Bool sixteen) { unsigned char *chars = (unsigned char *) s_chars; FontPtr font = gc->font; int off_x, off_y; int c; int nglyph; GLshort *v; char *vbo_offset; CharInfoPtr ci; int firstRow = font->info.firstRow; int firstCol = font->info.firstCol; int glyph_spacing_x = glamor_font->glyph_width_bytes * 8; int glyph_spacing_y = glamor_font->glyph_height; int box_x, box_y; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); /* Set the font as texture 1 */ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); glUniform1i(prog->font_uniform, 1); /* Set up the vertex buffers for the font and destination */ v = glamor_get_vbo_space(drawable->pScreen, count * (6 * sizeof (GLshort)), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, 6 * sizeof (GLshort), vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE, 6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort)); /* Set the vertex coordinates */ nglyph = 0; for (c = 0; c < count; c++) { if ((ci = *charinfo++)) { int x1 = x + ci->metrics.leftSideBearing; int y1 = y - ci->metrics.ascent; int width = GLYPHWIDTHPIXELS(ci); int height = GLYPHHEIGHTPIXELS(ci); int tx, ty = 0; int row = 0, col; x += ci->metrics.characterWidth; if (sixteen) { if (ci == glamor_font->default_char) { row = glamor_font->default_row; col = glamor_font->default_col; } else { row = chars[0]; col = chars[1]; } if (FONTLASTROW(font) != 0) ty = (row - firstRow) * glyph_spacing_y; else col += row << 8; } else { if (ci == glamor_font->default_char) col = glamor_font->default_col; else col = chars[0]; } tx = (col - firstCol) * glyph_spacing_x; v[ 0] = x1; v[ 1] = y1; v[ 2] = width; v[ 3] = height; v[ 4] = tx; v[ 5] = ty; v += 6; nglyph++; } chars += 1 + sixteen; } glamor_put_vbo_space(drawable->pScreen); if (nglyph != 0) { glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(pixmap_priv, box_x, box_y) { BoxPtr box = RegionRects(gc->pCompositeClip); int nbox = RegionNumRects(gc->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++; glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); } }
static Bool glamor_fill_spans_gl(DrawablePtr drawable, GCPtr gc, int n, DDXPointPtr points, int *widths, int sorted) { 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_program *prog; int off_x, off_y; GLshort *v; char *vbo_offset; int c; int box_x, box_y; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; glamor_make_current(glamor_priv); if (glamor_priv->glsl_version >= 130) { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, &glamor_facet_fillspans_130); if (!prog) goto bail; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE, 4 * sizeof (GLshort), vbo_offset); for (c = 0; c < n; c++) { v[0] = points->x; v[1] = points->y; v[2] = *widths++; points++; v += 4; } glamor_put_vbo_space(screen); } else { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, &glamor_facet_fillspans_120); if (!prog) goto bail; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 2 * sizeof (short), vbo_offset); for (c = 0; c < n; c++) { v[0] = points->x; v[1] = points->y; v[2] = points->x; v[3] = points->y + 1; v[4] = points->x + *widths; v[5] = points->y + 1; v[6] = points->x + *widths; v[7] = points->y; widths++; points++; v += 8; } glamor_put_vbo_space(screen); } glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(pixmap_priv, box_x, box_y) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, box->y1 + off_y, box->x2 - box->x1, box->y2 - box->y1); box++; if (glamor_priv->glsl_version >= 130) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n); else { glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox); } } }
static Bool glamor_poly_fill_rect_gl(DrawablePtr drawable, GCPtr gc, int nrect, xRectangle *prect) { 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_program *prog; int off_x, off_y; GLshort *v; char *vbo_offset; int box_x, box_y; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; glamor_get_context(glamor_priv); if (glamor_priv->glsl_version >= 130) { prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_fill_rect_program, &glamor_facet_polyfillrect_130); if (!prog) goto bail_ctx; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, 4 * sizeof (short), vbo_offset); memcpy(v, prect, nrect * sizeof (xRectangle)); glamor_put_vbo_space(screen); } else { int n; prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_fill_rect_program, &glamor_facet_polyfillrect_120); if (!prog) goto bail_ctx; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 2 * sizeof (short), vbo_offset); for (n = 0; n < nrect; n++) { v[0] = prect->x; v[1] = prect->y; v[2] = prect->x; v[3] = prect->y + prect->height; v[4] = prect->x + prect->width; v[5] = prect->y + prect->height; v[6] = prect->x + prect->width; v[7] = prect->y; prect++; v += 8; } glamor_put_vbo_space(screen); } glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(pixmap_priv, box_x, box_y) { int nbox = RegionNumRects(gc->pCompositeClip); BoxPtr box = RegionRects(gc->pCompositeClip); glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); while (nbox--) { glScissor(box->x1 + off_x, box->y1 + off_y, box->x2 - box->x1, box->y2 - box->y1); box++; if (glamor_priv->glsl_version >= 130) glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); else { if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glDrawArrays(GL_QUADS, 0, nrect * 4); } else { int i; for (i = 0; i < nrect; i++) { glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); } } } } }
static Bool glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, int start_x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyph_base) { 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_program *prog; RegionPtr clip = gc->pCompositeClip; int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; glamor_make_current(glamor_priv); prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs, &glamor_facet_poly_glyph_blt); if (!prog) goto bail; glEnableVertexAttribArray(GLAMOR_VERTEX_POS); start_x += drawable->x; y += drawable->y; glamor_pixmap_loop(pixmap_priv, box_index) { int x; int n; int num_points, max_points; INT16 *points = NULL; int off_x, off_y; char *vbo_offset; glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y); max_points = 500; num_points = 0; x = start_x; for (n = 0; n < nglyph; n++) { CharInfoPtr charinfo = ppci[n]; int w = GLYPHWIDTHPIXELS(charinfo); int h = GLYPHHEIGHTPIXELS(charinfo); uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); if (w && h) { int glyph_x = x + charinfo->metrics.leftSideBearing; int glyph_y = y - charinfo->metrics.ascent; int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); int xx, yy; for (yy = 0; yy < h; yy++) { uint8_t *glyph = glyphbits; for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) { int pt_x_i = glyph_x + xx; int pt_y_i = glyph_y + yy; if (!(*glyph & (1 << (xx & 7)))) continue; if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) continue; if (!num_points) { points = glamor_get_vbo_space(screen, max_points * (2 * sizeof (INT16)), &vbo_offset); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 0, vbo_offset); } *points++ = pt_x_i; *points++ = pt_y_i; num_points++; if (num_points == max_points) { glamor_put_vbo_space(screen); glDrawArrays(GL_POINTS, 0, num_points); num_points = 0; } } glyphbits += glyph_stride; } } x += charinfo->metrics.characterWidth; } if (num_points) { glamor_put_vbo_space(screen); glDrawArrays(GL_POINTS, 0, num_points); } }