From f796ef5122229cc4d43b6431caac6916af8a08fb Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 11 Jun 2016 23:14:22 +0100 Subject: [PATCH] fix drawing of text --- src/drawing/IDrawingContext.h | 2 +- src/drawing/NewDrawing.cpp | 4 +- src/drawing/drawing.h | 2 +- src/drawing/engines/SoftwareDrawingEngine.cpp | 14 +- .../engines/opengl/OpenGLDrawingEngine.cpp | 48 +++++-- src/drawing/engines/opengl/TextureCache.cpp | 130 ++++++++++++++---- src/drawing/engines/opengl/TextureCache.h | 37 +++++ src/drawing/string.c | 2 +- 8 files changed, 190 insertions(+), 49 deletions(-) diff --git a/src/drawing/IDrawingContext.h b/src/drawing/IDrawingContext.h index 17bfb84505..5c83258fcb 100644 --- a/src/drawing/IDrawingContext.h +++ b/src/drawing/IDrawingContext.h @@ -30,7 +30,7 @@ interface IDrawingContext virtual void FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) abstract; virtual void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) abstract; virtual void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) abstract; - virtual void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) abstract; virtual void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) abstract; virtual void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) abstract; + virtual void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) abstract; }; diff --git a/src/drawing/NewDrawing.cpp b/src/drawing/NewDrawing.cpp index acc84b6647..b3dd0b00a0 100644 --- a/src/drawing/NewDrawing.cpp +++ b/src/drawing/NewDrawing.cpp @@ -209,12 +209,12 @@ extern "C" } } - void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 * palette, uint8 * unknown) + void FASTCALL gfx_draw_glpyh(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 * palette) { if (_drawingEngine != nullptr) { IDrawingContext * dc = _drawingEngine->GetDrawingContext(dpi); - dc->DrawSpritePaletteSet(image, x, y, palette, unknown); + dc->DrawGlyph(image, x, y, palette); } } diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 4c0bbc0110..4cd3576b28 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -146,7 +146,7 @@ rct_g1_element* gfx_get_g1_element(int image_id); void sub_68371D(); void FASTCALL gfx_rle_sprite_to_buffer(const uint8* RESTRICT source_bits_pointer, uint8* RESTRICT dest_bits_pointer, const uint8* RESTRICT palette_pointer, const rct_drawpixelinfo * RESTRICT dpi, int image_type, int source_y_start, int height, int source_x_start, int width); void FASTCALL gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); -void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer); +void FASTCALL gfx_draw_glpyh(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8 * palette); void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage); void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 colour); diff --git a/src/drawing/engines/SoftwareDrawingEngine.cpp b/src/drawing/engines/SoftwareDrawingEngine.cpp index abb3423579..6bf113c305 100644 --- a/src/drawing/engines/SoftwareDrawingEngine.cpp +++ b/src/drawing/engines/SoftwareDrawingEngine.cpp @@ -170,9 +170,9 @@ public: void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) override; void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; - void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) override; void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; - void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour); + void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; + void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) override; void SetDPI(rct_drawpixelinfo * dpi); }; @@ -1007,11 +1007,6 @@ void SoftwareDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 gfx_draw_sprite_software(_dpi, image, x, y, tertiaryColour); } -void SoftwareDrawingContext::DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) -{ - gfx_draw_sprite_palette_set_software(_dpi, image, x, y, palette, unknown); -} - void SoftwareDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) { gfx_draw_sprite_raw_masked_software(_dpi, x, y, maskImage, colourImage); @@ -1028,6 +1023,11 @@ void SoftwareDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, u gfx_draw_sprite_palette_set_software(_dpi, image | 0x20000000, x, y, palette, nullptr); } +void SoftwareDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) +{ + gfx_draw_sprite_palette_set_software(_dpi, image, x, y, palette, nullptr); +} + void SoftwareDrawingContext::SetDPI(rct_drawpixelinfo * dpi) { _dpi = dpi; diff --git a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp index eb7d88c0cb..07a02d0a9e 100644 --- a/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -176,8 +176,6 @@ private: TextureCache * _textureCache = nullptr; - GLuint _vbo; - sint32 _offsetX; sint32 _offsetY; sint32 _clipLeft; @@ -198,9 +196,9 @@ public: void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; void DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2) override; void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; - void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) override; void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; void DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour) override; + void DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) override; void SetDPI(rct_drawpixelinfo * dpi); }; @@ -605,11 +603,6 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t _drawImageShader->Draw(left, top, right, bottom); } -void OpenGLDrawingContext::DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) -{ - DrawSprite(image, x, y, 0); -} - void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) { rct_g1_element * g1ElementMask = gfx_get_g1_element(maskImage & 0x7FFFF); @@ -693,6 +686,45 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin _drawImageShader->SetFlags(0); } +void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette) +{ + int g1Id = image & 0x7FFFF; + rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + + GLuint texture = _textureCache->GetOrLoadGlyphTexture(image, palette); + + sint32 drawOffsetX = g1Element->x_offset; + sint32 drawOffsetY = g1Element->y_offset; + sint32 drawWidth = (uint16)g1Element->width; + sint32 drawHeight = (uint16)g1Element->height; + + sint32 left = x + drawOffsetX; + sint32 top = y + drawOffsetY; + sint32 right = left + drawWidth; + sint32 bottom = top + drawHeight; + + if (left > right) + { + std::swap(left, right); + } + if (top > bottom) + { + std::swap(top, bottom); + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + _drawImageShader->Use(); + _drawImageShader->SetScreenSize(gScreenWidth, gScreenHeight); + _drawImageShader->SetClip(_clipLeft, _clipTop, _clipRight, _clipBottom); + _drawImageShader->SetTexture(texture); + _drawImageShader->Draw(left, top, right, bottom); + _drawImageShader->SetFlags(0); +} + void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi) { rct_drawpixelinfo * screenDPI = _engine->GetDPI(); diff --git a/src/drawing/engines/opengl/TextureCache.cpp b/src/drawing/engines/opengl/TextureCache.cpp index 9f94bc916c..bb73ed16a1 100644 --- a/src/drawing/engines/opengl/TextureCache.cpp +++ b/src/drawing/engines/opengl/TextureCache.cpp @@ -59,10 +59,23 @@ GLuint TextureCache::GetOrLoadImageTexture(uint32 image) GLuint texture = LoadImageTexture(image); _imageTextureMap[image] = texture; - // if ((_textures.size() % 100) == 0) - // { - // printf("Textures: %d\n", _textures.size()); - // } + return texture; +} + +GLuint TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palette) +{ + GlyphId glyphId; + glyphId.Image = image; + Memory::Copy(&glyphId.Palette, palette, sizeof(glyphId.Palette)); + + auto kvp = _glyphTextureMap.find(glyphId); + if (kvp != _glyphTextureMap.end()) + { + return kvp->second; + } + + GLuint texture = LoadGlyphTexture(image, palette); + _glyphTextureMap[glyphId] = texture; return texture; } @@ -80,35 +93,66 @@ GLuint TextureCache::LoadImageTexture(uint32 image) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); - delete [] (uint8 *) pixels32; + Memory::Free(pixels32); return texture; } -void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32* outWidth, uint32* outHeight) +GLuint TextureCache::LoadGlyphTexture(uint32 image, uint8 * palette) { - int g1Id = image & 0x7FFFF; - rct_g1_element * g1Element = gfx_get_g1_element(g1Id); + GLuint texture; + glGenTextures(1, &texture); - uint32 width = (uint32)g1Element->width; - uint32 height = (uint32)g1Element->height; + uint32 width, height; + void * pixels32 = GetGlyphAsARGB(image, palette, &width, &height); - size_t numPixels = width * height; - uint8 * pixels8 = new uint8[numPixels]; - Memory::Set(pixels8, 0, numPixels); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels32); - rct_drawpixelinfo dpi; - dpi.bits = pixels8; - dpi.pitch = 0; - dpi.x = 0; - dpi.y = 0; - dpi.width = width; - dpi.height = height; - dpi.zoom_level = 0; - gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); + Memory::Free(pixels32); - uint8 * pixels32 = new uint8[width * height * 4]; - uint8 * src = pixels8; + return texture; +} + +void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight) +{ + rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF); + sint32 width = g1Element->width; + sint32 height = g1Element->height; + + rct_drawpixelinfo * dpi = CreateDPI(width, height); + gfx_draw_sprite_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); + void * pixels32 = ConvertDPIto32bpp(dpi); + DeleteDPI(dpi); + + *outWidth = width; + *outHeight = height; + return pixels32; +} + +void * TextureCache::GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight) +{ + rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF); + sint32 width = g1Element->width; + sint32 height = g1Element->height; + + rct_drawpixelinfo * dpi = CreateDPI(width, height); + gfx_draw_sprite_palette_set_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr); + void * pixels32 = ConvertDPIto32bpp(dpi); + DeleteDPI(dpi); + + *outWidth = width; + *outHeight = height; + return pixels32; +} + +void * TextureCache::ConvertDPIto32bpp(const rct_drawpixelinfo * dpi) +{ + size_t numPixels = dpi->width * dpi->height; + uint8 * pixels32 = Memory::Allocate(numPixels * 4); + uint8 * src = dpi->bits; uint8 * dst = pixels32; for (size_t i = 0; i < numPixels; i++) { @@ -130,22 +174,50 @@ void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32* *dst++ = colour.a; } } - - delete[] pixels8; - - *outWidth = width; - *outHeight = height; return pixels32; } void TextureCache::FreeTextures() { + // Free images size_t numTextures = _imageTextureMap.size(); auto textures = std::vector(numTextures); for (auto kvp : _imageTextureMap) { textures.push_back(kvp.second); } + glDeleteTextures(textures.size(), textures.data()); + // Free glyphs + numTextures = _glyphTextureMap.size(); + textures.clear(); + textures.reserve(numTextures); + for (auto kvp : _glyphTextureMap) + { + textures.push_back(kvp.second); + } glDeleteTextures(textures.size(), textures.data()); } + +rct_drawpixelinfo * TextureCache::CreateDPI(sint32 width, sint32 height) +{ + size_t numPixels = width * height; + uint8 * pixels8 = Memory::Allocate(numPixels); + Memory::Set(pixels8, 0, numPixels); + + rct_drawpixelinfo * dpi = new rct_drawpixelinfo(); + dpi->bits = pixels8; + dpi->pitch = 0; + dpi->x = 0; + dpi->y = 0; + dpi->width = width; + dpi->height = height; + dpi->zoom_level = 0; + return dpi; +} + +void TextureCache::DeleteDPI(rct_drawpixelinfo* dpi) +{ + Memory::Free(dpi->bits); + delete dpi; +} diff --git a/src/drawing/engines/opengl/TextureCache.h b/src/drawing/engines/opengl/TextureCache.h index d0e9f54b8e..3f5e36673c 100644 --- a/src/drawing/engines/opengl/TextureCache.h +++ b/src/drawing/engines/opengl/TextureCache.h @@ -21,10 +21,40 @@ #include "../../../common.h" #include "OpenGLAPI.h" +struct rct_drawpixelinfo; + +struct GlyphId +{ + uint32 Image; + uint64 Palette; + + struct Hash + { + size_t operator()(const GlyphId &k) const + { + size_t hash = 0x3154A85E; + hash = k.Image * 7; + hash += (k.Palette & 0xFFFFFFFF) * 13; + hash += (k.Palette >> 32) * 23; + return hash; + } + }; + + struct Equal + { + bool operator()(const GlyphId &lhs, const GlyphId &rhs) const + { + return lhs.Image == rhs.Image && + lhs.Palette == rhs.Palette; + } + }; +}; + class TextureCache { private: std::unordered_map _imageTextureMap; + std::unordered_map _glyphTextureMap; SDL_Color _palette[256]; public: @@ -33,9 +63,16 @@ public: void SetPalette(const SDL_Color * palette); void InvalidateImage(uint32 image); GLuint GetOrLoadImageTexture(uint32 image); + GLuint GetOrLoadGlyphTexture(uint32 image, uint8 * palette); private: GLuint LoadImageTexture(uint32 image); + GLuint LoadGlyphTexture(uint32 image, uint8 * palette); void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight); + void * GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight); + void * ConvertDPIto32bpp(const rct_drawpixelinfo * dpi); void FreeTextures(); + + static rct_drawpixelinfo * CreateDPI(sint32 width, sint32 height); + static void DeleteDPI(rct_drawpixelinfo * dpi); }; diff --git a/src/drawing/string.c b/src/drawing/string.c index 12ee28304a..bf50c33535 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -924,7 +924,7 @@ static void ttf_draw_character_sprite(rct_drawpixelinfo *dpi, int codepoint, tex if (info->flags & TEXT_DRAW_FLAG_Y_OFFSET_EFFECT) { y += *info->y_offset++; } - gfx_draw_sprite_palette_set(dpi, sprite, x, y, info->palette, NULL); + gfx_draw_glpyh(dpi, sprite, x, y, info->palette); } info->x += characterWidth;