Cocoa Port: Improve the handling of HUD font rendering for OpenGL display views running on old drivers.

This commit is contained in:
rogerman 2022-05-05 14:29:53 -07:00
parent 6e26980d87
commit 180df28ce7
5 changed files with 95 additions and 37 deletions

View File

@ -90,6 +90,7 @@ void ClientDisplayPresenter::__InstanceInit(const ClientDisplayPresenterProperti
_scaleFactor = 1.0;
_hudObjectScale = 1.0;
_isHUDRenderMipmapped = false;
_isHUDVisible = false;
_showExecutionSpeed = false;
_showVideoFPS = true;
@ -566,6 +567,17 @@ void ClientDisplayPresenter::SetHUDObjectScale(float objectScale)
this->_hudObjectScale = objectScale;
}
bool ClientDisplayPresenter::WillHUDRenderMipmapped() const
{
return this->_isHUDRenderMipmapped;
}
void ClientDisplayPresenter::SetHUDRenderMipmapped(const bool mipmapState)
{
this->_isHUDRenderMipmapped = mipmapState;
}
bool ClientDisplayPresenter::GetHUDVisibility() const
{
return this->_isHUDVisible;

View File

@ -154,6 +154,7 @@ protected:
double _scaleFactor;
double _hudObjectScale;
bool _isHUDRenderMipmapped;
bool _isHUDVisible;
bool _showExecutionSpeed;
bool _showVideoFPS;
@ -260,6 +261,8 @@ public:
float GetHUDObjectScale() const;
virtual void SetHUDObjectScale(float objectScale);
bool WillHUDRenderMipmapped() const;
void SetHUDRenderMipmapped(const bool mipmapState);
bool GetHUDVisibility() const;
virtual void SetHUDVisibility(const bool visibleState);
bool GetHUDShowExecutionSpeed() const;

View File

@ -37,7 +37,7 @@ static const char *HUDOutputVertShader_100 = {"\
uniform bool renderFlipped; \n\
\n\
VARYING vec4 vtxColor; \n\
VARYING vec2 texCoord[1]; \n\
VARYING vec2 texCoord; \n\
\n\
void main() \n\
{ \n\
@ -53,7 +53,7 @@ static const char *HUDOutputVertShader_100 = {"\
vec2( 0.0, scalar)); \n\
\n\
vtxColor = inColor; \n\
texCoord[0] = inTexCoord0; \n\
texCoord = inTexCoord0; \n\
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
\n\
if (renderFlipped)\n\
@ -66,12 +66,12 @@ static const char *HUDOutputVertShader_100 = {"\
// FRAGMENT SHADER FOR HUD OUTPUT
static const char *HUDOutputFragShader_110 = {"\
VARYING vec4 vtxColor;\n\
VARYING vec2 texCoord[1];\n\
VARYING vec2 texCoord;\n\
uniform sampler2D tex;\n\
\n\
void main()\n\
{\n\
OUT_FRAG_COLOR = SAMPLE4_TEX_2D(tex, texCoord[0]) * vtxColor;\n\
OUT_FRAG_COLOR = SAMPLE4_TEX_2D(tex, texCoord) * vtxColor;\n\
}\n\
"};
@ -5076,25 +5076,7 @@ void OGLVideoOutput::Init()
(*this->_layerList)[i]->SetVisibility(wasPreviouslyVisibleList[i]);
}
// Render State Setup (common to both shaders and fixed-function pipeline)
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_STENCIL_TEST);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
// Set up fixed-function pipeline render states.
if (!this->_contextInfo->IsShaderSupported())
{
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
}
// Set up clear attributes
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
this->PrerenderStateSetupOGL();
// Set up textures
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
@ -5218,6 +5200,36 @@ void OGLVideoOutput::CopyFrameToBuffer(uint32_t *dstBuffer)
this->_needUpdateViewport = true;
}
void OGLVideoOutput::PrerenderStateSetupOGL()
{
// If the context is managed by us, then setting all of OpenGL's states
// once at initialization time should be enough.
//
// But if the context is managed by a third party, then this method can
// be manually called before rendering the video output if necessary.
//
// The most notable state here is enabling blending, which HUD rendering
// requires.
// Render State Setup (common to both shaders and fixed-function pipeline)
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_STENCIL_TEST);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Set up fixed-function pipeline render states.
if (!this->_contextInfo->IsShaderSupported())
{
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
}
}
void OGLVideoOutput::RenderFrameOGL(bool isRenderingFlipped)
{
if (this->_needUpdateViewport)
@ -6274,6 +6286,9 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
_uniformScalar = glGetUniformLocation(_program->GetProgramID(), "scalar");
_uniformViewSize = glGetUniformLocation(_program->GetProgramID(), "viewSize");
_uniformRenderFlipped = glGetUniformLocation(_program->GetProgramID(), "renderFlipped");
GLint uniformTexSampler = glGetUniformLocation(_program->GetProgramID(), "tex");
glUniform1i(uniformTexSampler, 0);
glUseProgram(0);
}
else
@ -6370,26 +6385,35 @@ OGLHUDLayer::~OGLHUDLayer()
void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, const size_t glyphTileSize, GlyphInfo *glyphInfo)
{
FT_Error error = FT_Err_Ok;
std::vector<uint32_t *> workingBufferList;
workingBufferList.reserve(16);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->_texCharMap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLint texLevel = 0;
for (size_t tileSize = glyphTileSize, gSize = glyphSize; tileSize >= 4; texLevel++, tileSize >>= 1, gSize = (GLfloat)tileSize * 0.75f)
for (size_t tileSize = glyphTileSize, texSize = glyphTileSize * 16, gSize = glyphSize; texSize >= 1; texLevel++, tileSize >>= 1, texSize >>= 1, gSize = (GLfloat)tileSize * 0.75f)
{
const size_t charMapBufferPixCount = (16 * tileSize) * (16 * tileSize);
const size_t charMapBufferPixCount = texSize * texSize;
const uint32_t fontColor = 0x00FFFFFF;
// Allocate a working buffer for FreeType to draw in. We then need to add
// it to a list so that we can deallocate the working buffer after OpenGL
// has copied the buffer to its associated texture.
uint32_t *charMapBuffer = (uint32_t *)malloc(charMapBufferPixCount * 2 * sizeof(uint32_t));
workingBufferList.push_back(charMapBuffer);
for (size_t i = 0; i < charMapBufferPixCount; i++)
{
charMapBuffer[i] = fontColor;
}
if (tileSize == 0)
{
continue;
}
error = FT_Set_Char_Size(fontFace, gSize << 6, gSize << 6, 72, 72);
if (error)
{
@ -6404,7 +6428,7 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c
for (size_t pixIndex = 0; pixIndex < tileSize; pixIndex++)
{
const uint32_t colorRGBA8888 = 0xFFFFFFFF;
charMapBuffer[(tileSize + pixIndex) + (rowIndex * (16 * tileSize))] = colorRGBA8888;
charMapBuffer[(tileSize + pixIndex) + (rowIndex * texSize)] = colorRGBA8888;
}
}
@ -6420,7 +6444,6 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c
const uint16_t tileOffsetX = (c & 0x0F) * tileSize;
const uint16_t tileOffsetY = (c >> 4) * tileSize;
const uint16_t tileOffsetY_texture = tileOffsetY - (tileSize - gSize + (gSize / 16));
const uint16_t texSize = tileSize * 16;
const GLuint glyphWidth = glyphSlot->bitmap.width;
if (tileSize == glyphTileSize)
@ -6444,12 +6467,19 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c
}
}
glTexImage2D(GL_TEXTURE_2D, texLevel, GL_RGBA, 16 * tileSize, 16 * tileSize, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, charMapBuffer);
glTexImage2D(GL_TEXTURE_2D, texLevel, GL_RGBA, texSize, texSize, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, charMapBuffer);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, texLevel - 1);
glBindTexture(GL_TEXTURE_2D, 0);
// Synchronize here, then free all previously allocated working buffers.
glFinish();
for (size_t i = 0; i < workingBufferList.size(); i++)
{
free(workingBufferList[i]);
}
}
void OGLHUDLayer::_UpdateVerticesOGL()
@ -6551,19 +6581,19 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
// First, draw the inputs.
if (this->_output->GetHUDShowInput())
{
const ClientDisplayPresenterProperties &cdv = this->_output->GetPresenterProperties();
const ClientDisplayPresenterProperties &cdp = this->_output->GetPresenterProperties();
if (this->_output->GetContextInfo()->IsShaderSupported())
{
glUniform1f(this->_uniformAngleDegrees, cdv.rotation);
glUniform1f(this->_uniformScalar, cdv.viewScale);
glUniform1f(this->_uniformAngleDegrees, cdp.rotation);
glUniform1f(this->_uniformScalar, cdp.viewScale);
}
else
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(cdv.rotation, 0.0f, 0.0f, 1.0f);
glScalef(cdv.viewScale, cdv.viewScale, 1.0f);
glRotatef(cdp.rotation, 0.0f, 0.0f, 1.0f);
glScalef(cdp.viewScale, cdp.viewScale, 1.0f);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -6616,7 +6646,15 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if (this->_output->WillHUDRenderMipmapped())
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.50f);
}
@ -6696,6 +6734,9 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_uniformViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize");
_uniformRenderFlipped = glGetUniformLocation(finalOutputProgramID, "renderFlipped");
_uniformBacklightIntensity = glGetUniformLocation(finalOutputProgramID, "backlightIntensity");
GLint uniformTexSampler = glGetUniformLocation(finalOutputProgramID, "tex");
glUniform1i(uniformTexSampler, 0);
glUseProgram(0);
}
else

View File

@ -455,6 +455,7 @@ public:
// Client view interface
virtual void ProcessDisplays();
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
virtual void PrerenderStateSetupOGL();
virtual void RenderFrameOGL(bool isRenderingFlipped);
virtual const OGLProcessedFrameInfo& GetProcessedFrameInfo();

View File

@ -1296,6 +1296,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"];
cdv->Get3DPresenter()->SetHUDFontPath([fontPath cStringUsingEncoding:NSUTF8StringEncoding]);
cdv->Get3DPresenter()->SetHUDRenderMipmapped(true);
if (scaleFactor != 1.0f)
{