135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2009 Intel Corporation 335c4bbdfSmrg * Copyright © 1998 Keith Packard 435c4bbdfSmrg * 535c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a 635c4bbdfSmrg * copy of this software and associated documentation files (the "Software"), 735c4bbdfSmrg * to deal in the Software without restriction, including without limitation 835c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 935c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the 1035c4bbdfSmrg * Software is furnished to do so, subject to the following conditions: 1135c4bbdfSmrg * 1235c4bbdfSmrg * The above copyright notice and this permission notice (including the next 1335c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the 1435c4bbdfSmrg * Software. 1535c4bbdfSmrg * 1635c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1735c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1835c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1935c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2035c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2135c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2235c4bbdfSmrg * IN THE SOFTWARE. 2335c4bbdfSmrg * 2435c4bbdfSmrg * Authors: 2535c4bbdfSmrg * Zhigang Gong <zhigang.gong@gmail.com> 2635c4bbdfSmrg * 2735c4bbdfSmrg */ 2835c4bbdfSmrg 2935c4bbdfSmrg#include "glamor_priv.h" 3035c4bbdfSmrg#include <dixfontstr.h> 3135c4bbdfSmrg#include "glamor_transform.h" 3235c4bbdfSmrg 3335c4bbdfSmrgstatic const glamor_facet glamor_facet_poly_glyph_blt = { 3435c4bbdfSmrg .name = "poly_glyph_blt", 3535c4bbdfSmrg .vs_vars = "attribute vec2 primitive;\n", 3635c4bbdfSmrg .vs_exec = (" vec2 pos = vec2(0,0);\n" 3735c4bbdfSmrg GLAMOR_POS(gl_Position, primitive)), 3835c4bbdfSmrg}; 3935c4bbdfSmrg 4035c4bbdfSmrgstatic Bool 4135c4bbdfSmrgglamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, 4235c4bbdfSmrg int start_x, int y, unsigned int nglyph, 4335c4bbdfSmrg CharInfoPtr *ppci, void *pglyph_base) 4435c4bbdfSmrg{ 4535c4bbdfSmrg ScreenPtr screen = drawable->pScreen; 4635c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 4735c4bbdfSmrg PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 4835c4bbdfSmrg glamor_pixmap_private *pixmap_priv; 4935c4bbdfSmrg glamor_program *prog; 5035c4bbdfSmrg RegionPtr clip = gc->pCompositeClip; 5135c4bbdfSmrg int box_index; 521b5d61b8Smrg Bool ret = FALSE; 5335c4bbdfSmrg 5435c4bbdfSmrg pixmap_priv = glamor_get_pixmap_private(pixmap); 5535c4bbdfSmrg if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 5635c4bbdfSmrg goto bail; 5735c4bbdfSmrg 5835c4bbdfSmrg glamor_make_current(glamor_priv); 5935c4bbdfSmrg 6035c4bbdfSmrg prog = glamor_use_program_fill(pixmap, gc, 6135c4bbdfSmrg &glamor_priv->poly_glyph_blt_progs, 6235c4bbdfSmrg &glamor_facet_poly_glyph_blt); 6335c4bbdfSmrg if (!prog) 6435c4bbdfSmrg goto bail; 6535c4bbdfSmrg 6635c4bbdfSmrg glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 6735c4bbdfSmrg 6835c4bbdfSmrg start_x += drawable->x; 6935c4bbdfSmrg y += drawable->y; 7035c4bbdfSmrg 7135c4bbdfSmrg glamor_pixmap_loop(pixmap_priv, box_index) { 7235c4bbdfSmrg int x; 7335c4bbdfSmrg int n; 7435c4bbdfSmrg int num_points, max_points; 7535c4bbdfSmrg INT16 *points = NULL; 7635c4bbdfSmrg int off_x, off_y; 7735c4bbdfSmrg char *vbo_offset; 7835c4bbdfSmrg 791b5d61b8Smrg if (!glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, 801b5d61b8Smrg prog->matrix_uniform, &off_x, &off_y)) 811b5d61b8Smrg goto bail; 8235c4bbdfSmrg 8335c4bbdfSmrg max_points = 500; 8435c4bbdfSmrg num_points = 0; 8535c4bbdfSmrg x = start_x; 8635c4bbdfSmrg for (n = 0; n < nglyph; n++) { 8735c4bbdfSmrg CharInfoPtr charinfo = ppci[n]; 8835c4bbdfSmrg int w = GLYPHWIDTHPIXELS(charinfo); 8935c4bbdfSmrg int h = GLYPHHEIGHTPIXELS(charinfo); 9035c4bbdfSmrg uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); 9135c4bbdfSmrg 9235c4bbdfSmrg if (w && h) { 9335c4bbdfSmrg int glyph_x = x + charinfo->metrics.leftSideBearing; 9435c4bbdfSmrg int glyph_y = y - charinfo->metrics.ascent; 9535c4bbdfSmrg int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); 9635c4bbdfSmrg int xx, yy; 9735c4bbdfSmrg 9835c4bbdfSmrg for (yy = 0; yy < h; yy++) { 9935c4bbdfSmrg uint8_t *glyph = glyphbits; 10035c4bbdfSmrg for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) { 10135c4bbdfSmrg int pt_x_i = glyph_x + xx; 10235c4bbdfSmrg int pt_y_i = glyph_y + yy; 10335c4bbdfSmrg 10458cf2af7Smrg#if BITMAP_BIT_ORDER == MSBFirst 10558cf2af7Smrg if (!(*glyph & (128 >> (xx & 7)))) 10658cf2af7Smrg#else 10735c4bbdfSmrg if (!(*glyph & (1 << (xx & 7)))) 10858cf2af7Smrg#endif 10935c4bbdfSmrg continue; 11035c4bbdfSmrg 11135c4bbdfSmrg if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) 11235c4bbdfSmrg continue; 11335c4bbdfSmrg 11435c4bbdfSmrg if (!num_points) { 11535c4bbdfSmrg points = glamor_get_vbo_space(screen, 11635c4bbdfSmrg max_points * 11735c4bbdfSmrg (2 * sizeof (INT16)), 11835c4bbdfSmrg &vbo_offset); 11935c4bbdfSmrg 12035c4bbdfSmrg glVertexAttribPointer(GLAMOR_VERTEX_POS, 12135c4bbdfSmrg 2, GL_SHORT, 12235c4bbdfSmrg GL_FALSE, 0, vbo_offset); 12335c4bbdfSmrg } 12435c4bbdfSmrg 12535c4bbdfSmrg *points++ = pt_x_i; 12635c4bbdfSmrg *points++ = pt_y_i; 12735c4bbdfSmrg num_points++; 12835c4bbdfSmrg 12935c4bbdfSmrg if (num_points == max_points) { 13035c4bbdfSmrg glamor_put_vbo_space(screen); 13135c4bbdfSmrg glDrawArrays(GL_POINTS, 0, num_points); 13235c4bbdfSmrg num_points = 0; 13335c4bbdfSmrg } 13435c4bbdfSmrg } 13535c4bbdfSmrg glyphbits += glyph_stride; 13635c4bbdfSmrg } 13735c4bbdfSmrg } 13835c4bbdfSmrg x += charinfo->metrics.characterWidth; 13935c4bbdfSmrg } 14035c4bbdfSmrg 14135c4bbdfSmrg if (num_points) { 14235c4bbdfSmrg glamor_put_vbo_space(screen); 14335c4bbdfSmrg glDrawArrays(GL_POINTS, 0, num_points); 14435c4bbdfSmrg } 14535c4bbdfSmrg } 14635c4bbdfSmrg 1471b5d61b8Smrg ret = TRUE; 14835c4bbdfSmrg 14935c4bbdfSmrgbail: 1501b5d61b8Smrg glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 1511b5d61b8Smrg 1521b5d61b8Smrg return ret; 15335c4bbdfSmrg} 15435c4bbdfSmrg 15535c4bbdfSmrgvoid 15635c4bbdfSmrgglamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc, 15735c4bbdfSmrg int start_x, int y, unsigned int nglyph, 15835c4bbdfSmrg CharInfoPtr *ppci, void *pglyph_base) 15935c4bbdfSmrg{ 16035c4bbdfSmrg if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, 16135c4bbdfSmrg pglyph_base)) 16235c4bbdfSmrg return; 16335c4bbdfSmrg miPolyGlyphBlt(drawable, gc, start_x, y, nglyph, 16435c4bbdfSmrg ppci, pglyph_base); 16535c4bbdfSmrg} 16635c4bbdfSmrg 16735c4bbdfSmrgstatic Bool 16835c4bbdfSmrgglamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, 16935c4bbdfSmrg DrawablePtr drawable, int w, int h, int x, int y) 17035c4bbdfSmrg{ 17135c4bbdfSmrg ScreenPtr screen = drawable->pScreen; 17235c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 17335c4bbdfSmrg PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 17435c4bbdfSmrg glamor_pixmap_private *pixmap_priv; 17535c4bbdfSmrg uint8_t *bitmap_data = bitmap->devPrivate.ptr; 17635c4bbdfSmrg int bitmap_stride = bitmap->devKind; 17735c4bbdfSmrg glamor_program *prog; 17835c4bbdfSmrg RegionPtr clip = gc->pCompositeClip; 17935c4bbdfSmrg int box_index; 18035c4bbdfSmrg int yy, xx; 18135c4bbdfSmrg int num_points; 18235c4bbdfSmrg INT16 *points = NULL; 18335c4bbdfSmrg char *vbo_offset; 1841b5d61b8Smrg Bool ret = FALSE; 18535c4bbdfSmrg 18635c4bbdfSmrg if (w * h > MAXINT / (2 * sizeof(float))) 18735c4bbdfSmrg goto bail; 18835c4bbdfSmrg 18935c4bbdfSmrg pixmap_priv = glamor_get_pixmap_private(pixmap); 19035c4bbdfSmrg if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 19135c4bbdfSmrg goto bail; 19235c4bbdfSmrg 19335c4bbdfSmrg glamor_make_current(glamor_priv); 19435c4bbdfSmrg 19535c4bbdfSmrg prog = glamor_use_program_fill(pixmap, gc, 19635c4bbdfSmrg &glamor_priv->poly_glyph_blt_progs, 19735c4bbdfSmrg &glamor_facet_poly_glyph_blt); 19835c4bbdfSmrg if (!prog) 19935c4bbdfSmrg goto bail; 20035c4bbdfSmrg 20135c4bbdfSmrg glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 20235c4bbdfSmrg 20335c4bbdfSmrg points = glamor_get_vbo_space(screen, w * h * sizeof(INT16) * 2, 20435c4bbdfSmrg &vbo_offset); 20535c4bbdfSmrg num_points = 0; 20635c4bbdfSmrg 20735c4bbdfSmrg /* Note that because fb sets miTranslate in the GC, our incoming X 20835c4bbdfSmrg * and Y are in screen coordinate space (same for spans, but not 20935c4bbdfSmrg * other operations). 21035c4bbdfSmrg */ 21135c4bbdfSmrg 21235c4bbdfSmrg for (yy = 0; yy < h; yy++) { 21335c4bbdfSmrg uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride; 21435c4bbdfSmrg for (xx = 0; xx < w; xx++) { 21558cf2af7Smrg#if BITMAP_BIT_ORDER == MSBFirst 21658cf2af7Smrg if (bitmap_row[xx / 8] & (128 >> xx % 8) && 21758cf2af7Smrg#else 21835c4bbdfSmrg if (bitmap_row[xx / 8] & (1 << xx % 8) && 21958cf2af7Smrg#endif 22035c4bbdfSmrg RegionContainsPoint(clip, 22135c4bbdfSmrg x + xx, 22235c4bbdfSmrg y + yy, 22335c4bbdfSmrg NULL)) { 22435c4bbdfSmrg *points++ = x + xx; 22535c4bbdfSmrg *points++ = y + yy; 22635c4bbdfSmrg num_points++; 22735c4bbdfSmrg } 22835c4bbdfSmrg } 22935c4bbdfSmrg } 23035c4bbdfSmrg glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, 23135c4bbdfSmrg GL_FALSE, 0, vbo_offset); 23235c4bbdfSmrg 23335c4bbdfSmrg glamor_put_vbo_space(screen); 23435c4bbdfSmrg 23535c4bbdfSmrg glamor_pixmap_loop(pixmap_priv, box_index) { 2361b5d61b8Smrg if (!glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, 2371b5d61b8Smrg prog->matrix_uniform, NULL, NULL)) 2381b5d61b8Smrg goto bail; 23935c4bbdfSmrg 24035c4bbdfSmrg glDrawArrays(GL_POINTS, 0, num_points); 24135c4bbdfSmrg } 24235c4bbdfSmrg 2431b5d61b8Smrg ret = TRUE; 24435c4bbdfSmrg 24535c4bbdfSmrgbail: 2461b5d61b8Smrg glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 2471b5d61b8Smrg 2481b5d61b8Smrg return ret; 24935c4bbdfSmrg} 25035c4bbdfSmrg 25135c4bbdfSmrgvoid 25235c4bbdfSmrgglamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 25335c4bbdfSmrg DrawablePtr pDrawable, int w, int h, int x, int y) 25435c4bbdfSmrg{ 25535c4bbdfSmrg if (glamor_push_pixels_gl(pGC, pBitmap, pDrawable, w, h, x, y)) 25635c4bbdfSmrg return; 25735c4bbdfSmrg 25835c4bbdfSmrg miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); 25935c4bbdfSmrg} 260