135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2014 Keith Packard 335c4bbdfSmrg * 435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 935c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1035c4bbdfSmrg * written prior permission. The copyright holders make no representations 1135c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1235c4bbdfSmrg * is" without express or implied warranty. 1335c4bbdfSmrg * 1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2035c4bbdfSmrg * OF THIS SOFTWARE. 2135c4bbdfSmrg */ 2235c4bbdfSmrg 2335c4bbdfSmrg#include "glamor_priv.h" 2435c4bbdfSmrg#include "glamor_font.h" 2535c4bbdfSmrg#include <dixfontstr.h> 2635c4bbdfSmrg 2735c4bbdfSmrgstatic int glamor_font_generation; 2835c4bbdfSmrgstatic int glamor_font_private_index; 2935c4bbdfSmrgstatic int glamor_font_screen_count; 3035c4bbdfSmrg 3135c4bbdfSmrgglamor_font_t * 3235c4bbdfSmrgglamor_font_get(ScreenPtr screen, FontPtr font) 3335c4bbdfSmrg{ 3435c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 3535c4bbdfSmrg 3635c4bbdfSmrg glamor_font_t *privates; 3735c4bbdfSmrg glamor_font_t *glamor_font; 3835c4bbdfSmrg int overall_width, overall_height; 3935c4bbdfSmrg int num_rows; 4035c4bbdfSmrg int num_cols; 4135c4bbdfSmrg int glyph_width_pixels; 4235c4bbdfSmrg int glyph_width_bytes; 4335c4bbdfSmrg int glyph_height; 4435c4bbdfSmrg int row, col; 4535c4bbdfSmrg unsigned char c[2]; 4635c4bbdfSmrg CharInfoPtr glyph; 4735c4bbdfSmrg unsigned long count; 4835c4bbdfSmrg char *bits; 4935c4bbdfSmrg 50ed6184dfSmrg if (!glamor_glsl_has_ints(glamor_priv)) 5135c4bbdfSmrg return NULL; 5235c4bbdfSmrg 5335c4bbdfSmrg privates = FontGetPrivate(font, glamor_font_private_index); 5435c4bbdfSmrg if (!privates) { 5535c4bbdfSmrg privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t)); 5635c4bbdfSmrg if (!privates) 5735c4bbdfSmrg return NULL; 581b5d61b8Smrg xfont2_font_set_private(font, glamor_font_private_index, privates); 5935c4bbdfSmrg } 6035c4bbdfSmrg 6135c4bbdfSmrg glamor_font = &privates[screen->myNum]; 6235c4bbdfSmrg 6335c4bbdfSmrg if (glamor_font->realized) 6435c4bbdfSmrg return glamor_font; 6535c4bbdfSmrg 6635c4bbdfSmrg /* Figure out how many glyphs are in the font */ 6735c4bbdfSmrg num_cols = font->info.lastCol - font->info.firstCol + 1; 6835c4bbdfSmrg num_rows = font->info.lastRow - font->info.firstRow + 1; 6935c4bbdfSmrg 7035c4bbdfSmrg /* Figure out the size of each glyph */ 7135c4bbdfSmrg glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing; 7235c4bbdfSmrg glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent; 7335c4bbdfSmrg 7435c4bbdfSmrg glyph_width_bytes = (glyph_width_pixels + 7) >> 3; 7535c4bbdfSmrg 7635c4bbdfSmrg glamor_font->glyph_width_pixels = glyph_width_pixels; 7735c4bbdfSmrg glamor_font->glyph_width_bytes = glyph_width_bytes; 7835c4bbdfSmrg glamor_font->glyph_height = glyph_height; 7935c4bbdfSmrg 8035c4bbdfSmrg /* 8135c4bbdfSmrg * Layout the font two blocks of columns wide. 8235c4bbdfSmrg * This avoids a problem with some fonts that are too high to fit. 8335c4bbdfSmrg */ 8435c4bbdfSmrg glamor_font->row_width = glyph_width_bytes * num_cols; 8535c4bbdfSmrg 8635c4bbdfSmrg if (num_rows > 1) { 8735c4bbdfSmrg overall_width = glamor_font->row_width * 2; 8835c4bbdfSmrg overall_height = glyph_height * ((num_rows + 1) / 2); 8935c4bbdfSmrg } else { 9035c4bbdfSmrg overall_width = glamor_font->row_width; 9135c4bbdfSmrg overall_height = glyph_height; 9235c4bbdfSmrg } 9335c4bbdfSmrg 9435c4bbdfSmrg if (overall_width > glamor_priv->max_fbo_size || 9535c4bbdfSmrg overall_height > glamor_priv->max_fbo_size) { 9635c4bbdfSmrg /* fallback if we don't fit inside a texture */ 9735c4bbdfSmrg return NULL; 9835c4bbdfSmrg } 9935c4bbdfSmrg bits = malloc(overall_width * overall_height); 10035c4bbdfSmrg if (!bits) 10135c4bbdfSmrg return NULL; 10235c4bbdfSmrg 10335c4bbdfSmrg /* Check whether the font has a default character */ 10435c4bbdfSmrg c[0] = font->info.lastRow + 1; 10535c4bbdfSmrg c[1] = font->info.lastCol + 1; 10635c4bbdfSmrg (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); 10735c4bbdfSmrg 10835c4bbdfSmrg glamor_font->default_char = count ? glyph : NULL; 10935c4bbdfSmrg glamor_font->default_row = font->info.defaultCh >> 8; 11035c4bbdfSmrg glamor_font->default_col = font->info.defaultCh; 11135c4bbdfSmrg 11235c4bbdfSmrg glamor_priv = glamor_get_screen_private(screen); 11335c4bbdfSmrg glamor_make_current(glamor_priv); 11435c4bbdfSmrg 11535c4bbdfSmrg glGenTextures(1, &glamor_font->texture_id); 11635c4bbdfSmrg glActiveTexture(GL_TEXTURE0); 11735c4bbdfSmrg glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); 11835c4bbdfSmrg 11935c4bbdfSmrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 12035c4bbdfSmrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 12135c4bbdfSmrg 12235c4bbdfSmrg /* Paint all of the glyphs */ 12335c4bbdfSmrg for (row = 0; row < num_rows; row++) { 12435c4bbdfSmrg for (col = 0; col < num_cols; col++) { 12535c4bbdfSmrg c[0] = row + font->info.firstRow; 12635c4bbdfSmrg c[1] = col + font->info.firstCol; 12735c4bbdfSmrg 12835c4bbdfSmrg (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); 12935c4bbdfSmrg 13035c4bbdfSmrg if (count) { 13135c4bbdfSmrg char *dst; 13235c4bbdfSmrg char *src = glyph->bits; 13335c4bbdfSmrg unsigned y; 13435c4bbdfSmrg 13535c4bbdfSmrg dst = bits; 13635c4bbdfSmrg /* get offset of start of first row */ 13735c4bbdfSmrg dst += (row / 2) * glyph_height * overall_width; 13835c4bbdfSmrg /* add offset into second row */ 13935c4bbdfSmrg dst += (row & 1) ? glamor_font->row_width : 0; 14035c4bbdfSmrg 14135c4bbdfSmrg dst += col * glyph_width_bytes; 14235c4bbdfSmrg for (y = 0; y < GLYPHHEIGHTPIXELS(glyph); y++) { 14335c4bbdfSmrg memcpy(dst, src, GLYPHWIDTHBYTES(glyph)); 14435c4bbdfSmrg dst += overall_width; 14535c4bbdfSmrg src += GLYPHWIDTHBYTESPADDED(glyph); 14635c4bbdfSmrg } 14735c4bbdfSmrg } 14835c4bbdfSmrg } 14935c4bbdfSmrg } 15035c4bbdfSmrg 15135c4bbdfSmrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 15235c4bbdfSmrg 15335c4bbdfSmrg glamor_priv->suppress_gl_out_of_memory_logging = true; 15435c4bbdfSmrg glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, 15535c4bbdfSmrg 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits); 15635c4bbdfSmrg glamor_priv->suppress_gl_out_of_memory_logging = false; 15735c4bbdfSmrg if (glGetError() == GL_OUT_OF_MEMORY) 15835c4bbdfSmrg return NULL; 15935c4bbdfSmrg 16035c4bbdfSmrg free(bits); 16135c4bbdfSmrg 16235c4bbdfSmrg glamor_font->realized = TRUE; 16335c4bbdfSmrg 16435c4bbdfSmrg return glamor_font; 16535c4bbdfSmrg} 16635c4bbdfSmrg 16735c4bbdfSmrgstatic Bool 16835c4bbdfSmrgglamor_realize_font(ScreenPtr screen, FontPtr font) 16935c4bbdfSmrg{ 17035c4bbdfSmrg return TRUE; 17135c4bbdfSmrg} 17235c4bbdfSmrg 17335c4bbdfSmrgstatic Bool 17435c4bbdfSmrgglamor_unrealize_font(ScreenPtr screen, FontPtr font) 17535c4bbdfSmrg{ 17635c4bbdfSmrg glamor_screen_private *glamor_priv; 17735c4bbdfSmrg glamor_font_t *privates = FontGetPrivate(font, glamor_font_private_index); 17835c4bbdfSmrg glamor_font_t *glamor_font; 17935c4bbdfSmrg int s; 18035c4bbdfSmrg 18135c4bbdfSmrg if (!privates) 18235c4bbdfSmrg return TRUE; 18335c4bbdfSmrg 18435c4bbdfSmrg glamor_font = &privates[screen->myNum]; 18535c4bbdfSmrg 18635c4bbdfSmrg if (!glamor_font->realized) 18735c4bbdfSmrg return TRUE; 18835c4bbdfSmrg 18935c4bbdfSmrg /* Unrealize the font, freeing the allocated texture */ 19035c4bbdfSmrg glamor_font->realized = FALSE; 19135c4bbdfSmrg 19235c4bbdfSmrg glamor_priv = glamor_get_screen_private(screen); 19335c4bbdfSmrg glamor_make_current(glamor_priv); 19435c4bbdfSmrg glDeleteTextures(1, &glamor_font->texture_id); 19535c4bbdfSmrg 19635c4bbdfSmrg /* Check to see if all of the screens are done with this font 19735c4bbdfSmrg * and free the private when that happens 19835c4bbdfSmrg */ 19935c4bbdfSmrg for (s = 0; s < glamor_font_screen_count; s++) 20035c4bbdfSmrg if (privates[s].realized) 20135c4bbdfSmrg return TRUE; 20235c4bbdfSmrg 20335c4bbdfSmrg free(privates); 2041b5d61b8Smrg xfont2_font_set_private(font, glamor_font_private_index, NULL); 20535c4bbdfSmrg return TRUE; 20635c4bbdfSmrg} 20735c4bbdfSmrg 20835c4bbdfSmrgBool 20935c4bbdfSmrgglamor_font_init(ScreenPtr screen) 21035c4bbdfSmrg{ 21135c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 21235c4bbdfSmrg 213ed6184dfSmrg if (!glamor_glsl_has_ints(glamor_priv)) 21435c4bbdfSmrg return TRUE; 21535c4bbdfSmrg 21635c4bbdfSmrg if (glamor_font_generation != serverGeneration) { 2171b5d61b8Smrg glamor_font_private_index = xfont2_allocate_font_private_index(); 21835c4bbdfSmrg if (glamor_font_private_index == -1) 21935c4bbdfSmrg return FALSE; 22035c4bbdfSmrg glamor_font_screen_count = 0; 22135c4bbdfSmrg glamor_font_generation = serverGeneration; 22235c4bbdfSmrg } 22335c4bbdfSmrg 22435c4bbdfSmrg if (screen->myNum >= glamor_font_screen_count) 22535c4bbdfSmrg glamor_font_screen_count = screen->myNum + 1; 22635c4bbdfSmrg 22735c4bbdfSmrg screen->RealizeFont = glamor_realize_font; 22835c4bbdfSmrg screen->UnrealizeFont = glamor_unrealize_font; 22935c4bbdfSmrg return TRUE; 23035c4bbdfSmrg} 231