xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

glamor_font.c (7769B)


      1 /*
      2  * Copyright © 2014 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "glamor_priv.h"
     24 #include "glamor_font.h"
     25 #include <dixfontstr.h>
     26 
     27 static int glamor_font_generation;
     28 static int glamor_font_private_index;
     29 static int glamor_font_screen_count;
     30 
     31 glamor_font_t *
     32 glamor_font_get(ScreenPtr screen, FontPtr font)
     33 {
     34     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     35 
     36     glamor_font_t       *privates;
     37     glamor_font_t       *glamor_font;
     38     int                 overall_width, overall_height;
     39     int                 num_rows;
     40     int                 num_cols;
     41     int                 glyph_width_pixels;
     42     int                 glyph_width_bytes;
     43     int                 glyph_height;
     44     int                 row, col;
     45     unsigned char       c[2];
     46     CharInfoPtr         glyph;
     47     unsigned long       count;
     48     char                *bits;
     49 
     50     if (!glamor_glsl_has_ints(glamor_priv))
     51         return NULL;
     52 
     53     privates = FontGetPrivate(font, glamor_font_private_index);
     54     if (!privates) {
     55         privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t));
     56         if (!privates)
     57             return NULL;
     58         xfont2_font_set_private(font, glamor_font_private_index, privates);
     59     }
     60 
     61     glamor_font = &privates[screen->myNum];
     62 
     63     if (glamor_font->realized)
     64         return glamor_font;
     65 
     66     /* Figure out how many glyphs are in the font */
     67     num_cols = font->info.lastCol - font->info.firstCol + 1;
     68     num_rows = font->info.lastRow - font->info.firstRow + 1;
     69 
     70     /* Figure out the size of each glyph */
     71     glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing;
     72     glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent;
     73 
     74     glyph_width_bytes = (glyph_width_pixels + 7) >> 3;
     75 
     76     glamor_font->glyph_width_pixels = glyph_width_pixels;
     77     glamor_font->glyph_width_bytes = glyph_width_bytes;
     78     glamor_font->glyph_height = glyph_height;
     79 
     80     /*
     81      * Layout the font two blocks of columns wide.
     82      * This avoids a problem with some fonts that are too high to fit.
     83      */
     84     glamor_font->row_width = glyph_width_bytes * num_cols;
     85 
     86     if (num_rows > 1) {
     87        overall_width = glamor_font->row_width * 2;
     88        overall_height = glyph_height * ((num_rows + 1) / 2);
     89     } else {
     90        overall_width = glamor_font->row_width;
     91        overall_height = glyph_height;
     92     }
     93 
     94     if (overall_width > glamor_priv->max_fbo_size ||
     95         overall_height > glamor_priv->max_fbo_size) {
     96         /* fallback if we don't fit inside a texture */
     97         return NULL;
     98     }
     99     bits = malloc(overall_width * overall_height);
    100     if (!bits)
    101         return NULL;
    102 
    103     /* Check whether the font has a default character */
    104     c[0] = font->info.lastRow + 1;
    105     c[1] = font->info.lastCol + 1;
    106     (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph);
    107 
    108     glamor_font->default_char = count ? glyph : NULL;
    109     glamor_font->default_row = font->info.defaultCh >> 8;
    110     glamor_font->default_col = font->info.defaultCh;
    111 
    112     glamor_priv = glamor_get_screen_private(screen);
    113     glamor_make_current(glamor_priv);
    114 
    115     glGenTextures(1, &glamor_font->texture_id);
    116     glActiveTexture(GL_TEXTURE0);
    117     glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id);
    118 
    119     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    120     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    121 
    122     /* Paint all of the glyphs */
    123     for (row = 0; row < num_rows; row++) {
    124         for (col = 0; col < num_cols; col++) {
    125             c[0] = row + font->info.firstRow;
    126             c[1] = col + font->info.firstCol;
    127 
    128             (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph);
    129 
    130             if (count) {
    131                 char *dst;
    132                 char *src = glyph->bits;
    133                 unsigned y;
    134 
    135                 dst = bits;
    136                 /* get offset of start of first row */
    137                 dst += (row / 2) * glyph_height * overall_width;
    138                 /* add offset into second row */
    139                 dst += (row & 1) ? glamor_font->row_width : 0;
    140 
    141                 dst += col * glyph_width_bytes;
    142                 for (y = 0; y < GLYPHHEIGHTPIXELS(glyph); y++) {
    143                     memcpy(dst, src, GLYPHWIDTHBYTES(glyph));
    144                     dst += overall_width;
    145                     src += GLYPHWIDTHBYTESPADDED(glyph);
    146                 }
    147             }
    148         }
    149     }
    150 
    151     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    152 
    153     glamor_priv->suppress_gl_out_of_memory_logging = true;
    154     glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height,
    155                  0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits);
    156     glamor_priv->suppress_gl_out_of_memory_logging = false;
    157     if (glGetError() == GL_OUT_OF_MEMORY)
    158         return NULL;
    159 
    160     free(bits);
    161 
    162     glamor_font->realized = TRUE;
    163 
    164     return glamor_font;
    165 }
    166 
    167 static Bool
    168 glamor_realize_font(ScreenPtr screen, FontPtr font)
    169 {
    170     return TRUE;
    171 }
    172 
    173 static Bool
    174 glamor_unrealize_font(ScreenPtr screen, FontPtr font)
    175 {
    176     glamor_screen_private       *glamor_priv;
    177     glamor_font_t               *privates = FontGetPrivate(font, glamor_font_private_index);
    178     glamor_font_t               *glamor_font;
    179     int                         s;
    180 
    181     if (!privates)
    182         return TRUE;
    183 
    184     glamor_font = &privates[screen->myNum];
    185 
    186     if (!glamor_font->realized)
    187         return TRUE;
    188 
    189     /* Unrealize the font, freeing the allocated texture */
    190     glamor_font->realized = FALSE;
    191 
    192     glamor_priv = glamor_get_screen_private(screen);
    193     glamor_make_current(glamor_priv);
    194     glDeleteTextures(1, &glamor_font->texture_id);
    195 
    196     /* Check to see if all of the screens are  done with this font
    197      * and free the private when that happens
    198      */
    199     for (s = 0; s < glamor_font_screen_count; s++)
    200         if (privates[s].realized)
    201             return TRUE;
    202 
    203     free(privates);
    204     xfont2_font_set_private(font, glamor_font_private_index, NULL);
    205     return TRUE;
    206 }
    207 
    208 Bool
    209 glamor_font_init(ScreenPtr screen)
    210 {
    211     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    212 
    213     if (!glamor_glsl_has_ints(glamor_priv))
    214         return TRUE;
    215 
    216     if (glamor_font_generation != serverGeneration) {
    217         glamor_font_private_index = xfont2_allocate_font_private_index();
    218         if (glamor_font_private_index == -1)
    219             return FALSE;
    220         glamor_font_screen_count = 0;
    221         glamor_font_generation = serverGeneration;
    222     }
    223 
    224     if (screen->myNum >= glamor_font_screen_count)
    225         glamor_font_screen_count = screen->myNum + 1;
    226 
    227     screen->RealizeFont = glamor_realize_font;
    228     screen->UnrealizeFont = glamor_unrealize_font;
    229     return TRUE;
    230 }