diff --git a/gfx/drivers_font/gl_raster_font.c b/gfx/drivers_font/gl_raster_font.c index c52b720745..5d057747b4 100644 --- a/gfx/drivers_font/gl_raster_font.c +++ b/gfx/drivers_font/gl_raster_font.c @@ -47,13 +47,94 @@ typedef struct gfx_font_raster_block_t *block; } gl_raster_t; +static void gl_raster_font_free_font(void *data); + +static bool gl_raster_font_upload_atlas(gl_raster_t *font, + const struct font_atlas *atlas, + unsigned width, unsigned height) +{ + unsigned i, j; + GLint gl_internal = GL_LUMINANCE_ALPHA; + GLenum gl_format = GL_LUMINANCE_ALPHA; + size_t ncomponents = 2; + uint8_t *tmp = NULL; + struct retro_hw_render_callback *cb = video_driver_callback(); + bool ancient = false; /* add a check here if needed */ + bool modern = font->gl->core_context || + (cb->context_type == RETRO_HW_CONTEXT_OPENGL && + cb->version_major >= 3); + + if (ancient) + { + gl_internal = gl_format = GL_RGBA; + ncomponents = 4; + } +#ifdef HAVE_OPENGLES + (void)modern; +#else + else if (modern) + { + GLint swizzle[] = { GL_ONE, GL_ONE, GL_ONE, GL_RED }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + + gl_internal = GL_R8; + gl_format = GL_RED; + ncomponents = 1; + } +#endif + + tmp = (uint8_t*)calloc(height, width * ncomponents); + + if (!tmp) + return false; + + for (i = 0; i < atlas->height; ++i) + { + const uint8_t *src = &atlas->buffer[i * atlas->width]; + uint8_t *dst = &tmp[i * width * ncomponents]; + + switch (ncomponents) + { + case 1: + memcpy(dst, src, atlas->width); + src += atlas->width; + break; + case 2: + for (j = 0; j < atlas->width; ++j) + { + *dst++ = 0xff; + *dst++ = *src++; + } + break; + case 4: + for (j = 0; j < atlas->width; ++j) + { + *dst++ = 0xff; + *dst++ = 0xff; + *dst++ = 0xff; + *dst++ = *src++; + } + break; + default: + RARCH_ERR("Unsupported number of components: %u\n", (unsigned)ncomponents); + free(tmp); + return false; + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, gl_internal, width, height, + 0, gl_format, GL_UNSIGNED_BYTE, tmp); + + free(tmp); + + return true; +} + static void *gl_raster_font_init_font(void *data, const char *font_path, float font_size) { - unsigned width, height; - uint8_t *tmp_buffer; const struct font_atlas *atlas = NULL; - gl_raster_t *font = (gl_raster_t*)calloc(1, sizeof(*font)); + gl_raster_t *font = (gl_raster_t*)calloc(1, sizeof(*font)); if (!font) return NULL; @@ -77,39 +158,15 @@ static void *gl_raster_font_init_font(void *data, atlas = font->font_driver->get_atlas(font->font_data); - width = next_pow2(atlas->width); - height = next_pow2(atlas->height); + font->tex_width = next_pow2(atlas->width);; + font->tex_height = next_pow2(atlas->height);; - /* Ideally, we'd use single component textures, but the - * difference in ways to do that between core GL and GLES/legacy GL - * is too great to bother going down that route. */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - tmp_buffer = (uint8_t*)malloc(atlas->width * atlas->height * 4); - - if (tmp_buffer) + if (!gl_raster_font_upload_atlas(font, atlas, font->tex_width, font->tex_height)) { - unsigned i; - uint8_t *dst = tmp_buffer; - const uint8_t *src = atlas->buffer; - - for (i = 0; i < atlas->width * atlas->height; i++) - { - *dst++ = 0xff; - *dst++ = 0xff; - *dst++ = 0xff; - *dst++ = *src++; - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlas->width, - atlas->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buffer); - free(tmp_buffer); + gl_raster_font_free_font(font); + font = NULL; } - font->tex_width = width; - font->tex_height = height; - glBindTexture(GL_TEXTURE_2D, font->gl->texture[font->gl->tex_index]); return font;