mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
GraphicsDrawer WIP
This commit is contained in:
parent
f92dd70d36
commit
fa3e7a0584
|
@ -438,7 +438,7 @@
|
||||||
<ClInclude Include="..\..\src\Graphics\CombinerProgram.h" />
|
<ClInclude Include="..\..\src\Graphics\CombinerProgram.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\Context.h" />
|
<ClInclude Include="..\..\src\Graphics\Context.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\ContextImpl.h" />
|
<ClInclude Include="..\..\src\Graphics\ContextImpl.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\DrawerImpl.h" />
|
<ClInclude Include="..\..\src\Graphics\GraphicsDrawerImpl.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\ObjectHandle.h" />
|
<ClInclude Include="..\..\src\Graphics\ObjectHandle.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLFunctions.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLFunctions.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerInputs.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerInputs.h" />
|
||||||
|
@ -454,6 +454,7 @@
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_CachedFunctions.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_CachedFunctions.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_ContextImpl.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_ContextImpl.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_GLInfo.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_GLInfo.h" />
|
||||||
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_DummyTextDrawer.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_TextureManipulationObjectFactory.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_TextureManipulationObjectFactory.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_UnbufferedDrawer.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_UnbufferedDrawer.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_Utils.h" />
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_Utils.h" />
|
||||||
|
@ -461,6 +462,7 @@
|
||||||
<ClInclude Include="..\..\src\Graphics\Parameters.h" />
|
<ClInclude Include="..\..\src\Graphics\Parameters.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\PixelBuffer.h" />
|
<ClInclude Include="..\..\src\Graphics\PixelBuffer.h" />
|
||||||
<ClInclude Include="..\..\src\Graphics\ShaderProgram.h" />
|
<ClInclude Include="..\..\src\Graphics\ShaderProgram.h" />
|
||||||
|
<ClInclude Include="..\..\src\Graphics\TextDrawerImpl.h" />
|
||||||
<ClInclude Include="..\..\src\gSP.h" />
|
<ClInclude Include="..\..\src\gSP.h" />
|
||||||
<ClInclude Include="..\..\src\inc\glext.h" />
|
<ClInclude Include="..\..\src\inc\glext.h" />
|
||||||
<ClInclude Include="..\..\src\Keys.h" />
|
<ClInclude Include="..\..\src\Keys.h" />
|
||||||
|
|
|
@ -628,14 +628,20 @@
|
||||||
<ClInclude Include="..\..\src\DisplayWindow.h">
|
<ClInclude Include="..\..\src\DisplayWindow.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\Graphics\DrawerImpl.h">
|
|
||||||
<Filter>Header Files\Graphics</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_UnbufferedDrawer.h">
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_UnbufferedDrawer.h">
|
||||||
<Filter>Header Files\Graphics\OpenGL</Filter>
|
<Filter>Header Files\Graphics\OpenGL</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\GraphicsDrawer.h">
|
<ClInclude Include="..\..\src\GraphicsDrawer.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\Graphics\GraphicsDrawerImpl.h">
|
||||||
|
<Filter>Header Files\Graphics</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\Graphics\TextDrawerImpl.h">
|
||||||
|
<Filter>Header Files\Graphics</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_DummyTextDrawer.h">
|
||||||
|
<Filter>Header Files\Graphics\OpenGL</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -63,6 +63,16 @@ void Context::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
||||||
m_impl->setBlendColor(_red, _green, _blue, _alpha);
|
m_impl->setBlendColor(_red, _green, _blue, _alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
||||||
|
{
|
||||||
|
m_impl->clearColorBuffer(_red, _green, _blue, _alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Context::clearDepthBuffer()
|
||||||
|
{
|
||||||
|
m_impl->clearDepthBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
ObjectHandle Context::createTexture(Parameter _target)
|
ObjectHandle Context::createTexture(Parameter _target)
|
||||||
{
|
{
|
||||||
return m_impl->createTexture(_target);
|
return m_impl->createTexture(_target);
|
||||||
|
@ -163,6 +173,16 @@ DrawerImpl * Context::createDrawerImpl()
|
||||||
return m_impl->createDrawerImpl();
|
return m_impl->createDrawerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextDrawer * Context::createTextDrawer()
|
||||||
|
{
|
||||||
|
return m_impl->createTextDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 Context::getMaxLineWidth()
|
||||||
|
{
|
||||||
|
return m_impl->getMaxLineWidth();
|
||||||
|
}
|
||||||
|
|
||||||
bool Context::isSupported(SpecialFeatures _feature) const
|
bool Context::isSupported(SpecialFeatures _feature) const
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
#include "CombinerProgram.h"
|
#include "CombinerProgram.h"
|
||||||
#include "ShaderProgram.h"
|
#include "ShaderProgram.h"
|
||||||
#include "PixelBuffer.h"
|
#include "PixelBuffer.h"
|
||||||
#include "DrawerImpl.h"
|
#include "GraphicsDrawerImpl.h"
|
||||||
|
#include "TextDrawerImpl.h"
|
||||||
|
|
||||||
#define GRAPHICS_CONTEXT
|
#define GRAPHICS_CONTEXT
|
||||||
|
|
||||||
|
@ -47,6 +48,10 @@ namespace graphics {
|
||||||
|
|
||||||
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
||||||
|
|
||||||
|
void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
||||||
|
|
||||||
|
void clearDepthBuffer();
|
||||||
|
|
||||||
ObjectHandle createTexture(Parameter _target);
|
ObjectHandle createTexture(Parameter _target);
|
||||||
|
|
||||||
void deleteTexture(ObjectHandle _name);
|
void deleteTexture(ObjectHandle _name);
|
||||||
|
@ -144,6 +149,10 @@ namespace graphics {
|
||||||
|
|
||||||
DrawerImpl * createDrawerImpl();
|
DrawerImpl * createDrawerImpl();
|
||||||
|
|
||||||
|
TextDrawer * createTextDrawer();
|
||||||
|
|
||||||
|
f32 getMaxLineWidth();
|
||||||
|
|
||||||
bool isSupported(SpecialFeatures _feature) const;
|
bool isSupported(SpecialFeatures _feature) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace graphics {
|
||||||
virtual void setScissor(s32 _x, s32 _y, s32 _width, s32 _height) = 0;
|
virtual void setScissor(s32 _x, s32 _y, s32 _width, s32 _height) = 0;
|
||||||
virtual void setBlending(Parameter _sfactor, Parameter _dfactor) = 0;
|
virtual void setBlending(Parameter _sfactor, Parameter _dfactor) = 0;
|
||||||
virtual void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0;
|
virtual void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0;
|
||||||
|
virtual void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0;
|
||||||
|
virtual void clearDepthBuffer() = 0;
|
||||||
virtual ObjectHandle createTexture(Parameter _target) = 0;
|
virtual ObjectHandle createTexture(Parameter _target) = 0;
|
||||||
virtual void deleteTexture(ObjectHandle _name) = 0;
|
virtual void deleteTexture(ObjectHandle _name) = 0;
|
||||||
virtual void init2DTexture(const Context::InitTextureParams & _params) = 0;
|
virtual void init2DTexture(const Context::InitTextureParams & _params) = 0;
|
||||||
|
@ -40,6 +42,8 @@ namespace graphics {
|
||||||
virtual ShaderProgram * createTexDrawerClearShader() = 0;
|
virtual ShaderProgram * createTexDrawerClearShader() = 0;
|
||||||
virtual ShaderProgram * createTexrectCopyShader() = 0;
|
virtual ShaderProgram * createTexrectCopyShader() = 0;
|
||||||
virtual DrawerImpl * createDrawerImpl() = 0;
|
virtual DrawerImpl * createDrawerImpl() = 0;
|
||||||
|
virtual TextDrawer * createTextDrawer() = 0;
|
||||||
|
virtual f32 getMaxLineWidth() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef GRAPHICS_DRAWERIMPL_H
|
#ifndef GRAPHICS_DRAWERIMPL_H
|
||||||
#define GRAPHICS_DRAWERIMPL_H
|
#define GRAPHICS_DRAWERIMPL_H
|
||||||
|
#include <array>
|
||||||
#include <GraphicsDrawer.h>
|
#include <GraphicsDrawer.h>
|
||||||
#include "Parameter.h"
|
#include "Parameter.h"
|
||||||
#include "CombinerProgram.h"
|
#include "CombinerProgram.h"
|
||||||
|
@ -27,12 +28,13 @@ namespace graphics {
|
||||||
{
|
{
|
||||||
Parameter mode;
|
Parameter mode;
|
||||||
u32 verticesCount = 0;
|
u32 verticesCount = 0;
|
||||||
f32 rectColor[4];
|
std::array<f32, 4> rectColor;
|
||||||
RectVertex * vertices = nullptr;
|
RectVertex * vertices = nullptr;
|
||||||
const CombinerProgram * combiner = nullptr;
|
const CombinerProgram * combiner = nullptr;
|
||||||
};
|
};
|
||||||
virtual void drawRects(const DrawRectParameters & _params) = 0;
|
virtual void drawRects(const DrawRectParameters & _params) = 0;
|
||||||
|
|
||||||
|
virtual void drawLine(f32 _width, SPVertex * vertices) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,14 @@ void CachedBlendColor::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha
|
||||||
glBlendColor(_red, _green, _blue, _alpha);
|
glBlendColor(_red, _green, _blue, _alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*---------------CachedClearColor-------------*/
|
||||||
|
|
||||||
|
void CachedClearColor::setClearColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
||||||
|
{
|
||||||
|
if (update(Parameter(_red), Parameter(_green), Parameter(_blue), Parameter(_alpha)))
|
||||||
|
glClearColor(_red, _green, _blue, _alpha);
|
||||||
|
}
|
||||||
|
|
||||||
/*---------------CachedVertexAttribArray-------------*/
|
/*---------------CachedVertexAttribArray-------------*/
|
||||||
|
|
||||||
void CachedVertexAttribArray::enableVertexAttribArray(u32 _index, bool _enable)
|
void CachedVertexAttribArray::enableVertexAttribArray(u32 _index, bool _enable)
|
||||||
|
@ -150,6 +158,7 @@ void CachedFunctions::reset()
|
||||||
m_scissor.reset();
|
m_scissor.reset();
|
||||||
m_blending.reset();
|
m_blending.reset();
|
||||||
m_blendColor.reset();
|
m_blendColor.reset();
|
||||||
|
m_clearColor.reset();
|
||||||
m_attribArray.reset();
|
m_attribArray.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +235,12 @@ CachedBlendColor * CachedFunctions::getCachedBlendColor()
|
||||||
return &m_blendColor;
|
return &m_blendColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CachedClearColor * CachedFunctions::getCachedClearColor()
|
||||||
|
{
|
||||||
|
return &m_clearColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CachedVertexAttribArray * CachedFunctions::getCachedVertexAttribArray()
|
CachedVertexAttribArray * CachedFunctions::getCachedVertexAttribArray()
|
||||||
{
|
{
|
||||||
return &m_attribArray;
|
return &m_attribArray;
|
||||||
|
|
|
@ -180,6 +180,12 @@ namespace opengl {
|
||||||
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CachedClearColor : public Cached4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void setClearColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
|
||||||
|
};
|
||||||
|
|
||||||
class CachedVertexAttribArray {
|
class CachedVertexAttribArray {
|
||||||
public:
|
public:
|
||||||
void enableVertexAttribArray(u32 _index, bool _enable);
|
void enableVertexAttribArray(u32 _index, bool _enable);
|
||||||
|
@ -225,6 +231,8 @@ namespace opengl {
|
||||||
|
|
||||||
CachedBlendColor * getCachedBlendColor();
|
CachedBlendColor * getCachedBlendColor();
|
||||||
|
|
||||||
|
CachedClearColor * getCachedClearColor();
|
||||||
|
|
||||||
CachedVertexAttribArray * getCachedVertexAttribArray();
|
CachedVertexAttribArray * getCachedVertexAttribArray();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -243,6 +251,7 @@ namespace opengl {
|
||||||
CachedScissor m_scissor;
|
CachedScissor m_scissor;
|
||||||
CachedBlending m_blending;
|
CachedBlending m_blending;
|
||||||
CachedBlendColor m_blendColor;
|
CachedBlendColor m_blendColor;
|
||||||
|
CachedClearColor m_clearColor;
|
||||||
CachedVertexAttribArray m_attribArray;
|
CachedVertexAttribArray m_attribArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <Log.h>
|
#include <Log.h>
|
||||||
|
#include <Graphics/Parameters.h>
|
||||||
#include "opengl_ContextImpl.h"
|
#include "opengl_ContextImpl.h"
|
||||||
#include "opengl_UnbufferedDrawer.h"
|
#include "opengl_UnbufferedDrawer.h"
|
||||||
|
#include "opengl_DummyTextDrawer.h"
|
||||||
#include "GLSL/glsl_CombinerProgramBuilder.h"
|
#include "GLSL/glsl_CombinerProgramBuilder.h"
|
||||||
#include "GLSL/glsl_SpecialShadersFactory.h"
|
#include "GLSL/glsl_SpecialShadersFactory.h"
|
||||||
#include "GLSL/glsl_ShaderStorage.h"
|
#include "GLSL/glsl_ShaderStorage.h"
|
||||||
|
@ -98,7 +100,35 @@ void ContextImpl::setBlending(graphics::Parameter _sfactor, graphics::Parameter
|
||||||
|
|
||||||
void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
||||||
{
|
{
|
||||||
|
m_cachedFunctions->getCachedBlendColor()->setBlendColor(_red, _green, _blue, _alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextImpl::clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
||||||
|
{
|
||||||
|
CachedEnable * enableScissor = m_cachedFunctions->getCachedEnable(graphics::enable::SCISSOR_TEST);
|
||||||
|
enableScissor->enable(false);
|
||||||
|
|
||||||
|
m_cachedFunctions->getCachedClearColor()->setClearColor(_red, _green, _blue, _alpha);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
enableScissor->enable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextImpl::clearDepthBuffer()
|
||||||
|
{
|
||||||
|
CachedEnable * enableScissor = m_cachedFunctions->getCachedEnable(graphics::enable::SCISSOR_TEST);
|
||||||
|
CachedDepthMask * depthMask = m_cachedFunctions->getCachedDepthMask();
|
||||||
|
enableScissor->enable(false);
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
depthMask->setDepthMask(false);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
depthMask->setDepthMask(true);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
enableScissor->enable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics::ObjectHandle ContextImpl::createTexture(graphics::Parameter _target)
|
graphics::ObjectHandle ContextImpl::createTexture(graphics::Parameter _target)
|
||||||
|
@ -224,5 +254,17 @@ graphics::ShaderProgram * ContextImpl::createTexrectCopyShader()
|
||||||
|
|
||||||
graphics::DrawerImpl * ContextImpl::createDrawerImpl()
|
graphics::DrawerImpl * ContextImpl::createDrawerImpl()
|
||||||
{
|
{
|
||||||
return new UnbufferedDrawer(m_cachedFunctions->getCachedVertexAttribArray());
|
return new UnbufferedDrawer(m_glInfo, m_cachedFunctions->getCachedVertexAttribArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::TextDrawer * ContextImpl::createTextDrawer()
|
||||||
|
{
|
||||||
|
return new DummyTextDrawer;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 ContextImpl::getMaxLineWidth()
|
||||||
|
{
|
||||||
|
GLfloat lineWidthRange[2] = { 0.0f, 0.0f };
|
||||||
|
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
|
||||||
|
return lineWidthRange[1];
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ namespace opengl {
|
||||||
|
|
||||||
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) override;
|
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) override;
|
||||||
|
|
||||||
|
void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha) override;
|
||||||
|
|
||||||
|
void clearDepthBuffer() override;
|
||||||
|
|
||||||
graphics::ObjectHandle createTexture(graphics::Parameter _target) override;
|
graphics::ObjectHandle createTexture(graphics::Parameter _target) override;
|
||||||
|
|
||||||
void deleteTexture(graphics::ObjectHandle _name) override;
|
void deleteTexture(graphics::ObjectHandle _name) override;
|
||||||
|
@ -78,6 +82,10 @@ namespace opengl {
|
||||||
|
|
||||||
graphics::DrawerImpl * createDrawerImpl() override;
|
graphics::DrawerImpl * createDrawerImpl() override;
|
||||||
|
|
||||||
|
graphics::TextDrawer * createTextDrawer() override;
|
||||||
|
|
||||||
|
f32 getMaxLineWidth() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CachedFunctions> m_cachedFunctions;
|
std::unique_ptr<CachedFunctions> m_cachedFunctions;
|
||||||
std::unique_ptr<Create2DTexture> m_createTexture;
|
std::unique_ptr<Create2DTexture> m_createTexture;
|
||||||
|
|
20
src/Graphics/OpenGLContext/opengl_DummyTextDrawer.h
Normal file
20
src/Graphics/OpenGLContext/opengl_DummyTextDrawer.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef OPENGL_DUMMY_TEXTDRAWER_H
|
||||||
|
#define OPENGL_DUMMY_TEXTDRAWER_H
|
||||||
|
|
||||||
|
#include <Graphics/TextDrawerImpl.h>
|
||||||
|
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
class DummyTextDrawer : public graphics::TextDrawer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DummyTextDrawer() {}
|
||||||
|
~DummyTextDrawer() {}
|
||||||
|
|
||||||
|
void renderText(const char *_pText, float x, float y) const override {}
|
||||||
|
void getTextSize(const char *_pText, float & _w, float & _h) const override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGL_DUMMY_TEXTDRAWER_H
|
408
src/Graphics/OpenGLContext/opengl_TextDrawerImpl.cpp
Normal file
408
src/Graphics/OpenGLContext/opengl_TextDrawerImpl.cpp
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
/* Draw text on screen.
|
||||||
|
* Requires freetype library.
|
||||||
|
* Code is taken from "OpenGL source examples from the OpenGL Programming wikibook:
|
||||||
|
* http://en.wikibooks.org/wiki/OpenGL_Programming"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include "opengl_TextDrawerImpl.h"
|
||||||
|
#include <RSP.h>
|
||||||
|
#include <Config.h>
|
||||||
|
#include <FBOTextureFormats.h>
|
||||||
|
#include <Log.h>
|
||||||
|
|
||||||
|
#include <Graphics/Context.h>
|
||||||
|
#include <Graphics/Parameters.h>
|
||||||
|
|
||||||
|
//#include "ShaderUtils.h"
|
||||||
|
|
||||||
|
struct point {
|
||||||
|
GLfloat x;
|
||||||
|
GLfloat y;
|
||||||
|
GLfloat s;
|
||||||
|
GLfloat t;
|
||||||
|
point() : x(0), y(0), s(0), t(0) {}
|
||||||
|
point(GLfloat _x, GLfloat _y, GLfloat _s, GLfloat _t) : x(_x), y(_y), s(_s), t(_t) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Maximum texture width
|
||||||
|
#define MAXWIDTH 1024
|
||||||
|
|
||||||
|
#if defined(GLES3_1)
|
||||||
|
#define SHADER_VERSION "#version 310 es \n"
|
||||||
|
#elif defined(GLES3)
|
||||||
|
#define SHADER_VERSION "#version 300 es \n"
|
||||||
|
#elif defined(GLES2)
|
||||||
|
#define SHADER_VERSION "#version 100 \n"
|
||||||
|
#else
|
||||||
|
#define SHADER_VERSION "#version 330 core \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GLES2
|
||||||
|
const GLenum monohromeformat = GL_LUMINANCE;
|
||||||
|
const GLenum monohromeInternalformat = GL_LUMINANCE;
|
||||||
|
#else
|
||||||
|
const GLenum monohromeformat = GL_RED;
|
||||||
|
const GLenum monohromeInternalformat = GL_R8;
|
||||||
|
#endif // GLES2
|
||||||
|
|
||||||
|
static
|
||||||
|
const char * strDrawTextVertexShader =
|
||||||
|
SHADER_VERSION
|
||||||
|
"#if (__VERSION__ > 120) \n"
|
||||||
|
"# define IN in \n"
|
||||||
|
"# define OUT out \n"
|
||||||
|
"#else \n"
|
||||||
|
"# define IN attribute \n"
|
||||||
|
"# define OUT varying \n"
|
||||||
|
"#endif // __VERSION \n"
|
||||||
|
"IN highp vec4 aRectPosition; \n"
|
||||||
|
"OUT mediump vec2 texpos; \n"
|
||||||
|
"void main(void) { \n"
|
||||||
|
" gl_Position = vec4(aRectPosition.xy, 0, 1); \n"
|
||||||
|
" texpos = aRectPosition.zw; \n"
|
||||||
|
"} \n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static
|
||||||
|
const char * strDrawTextFragmentShader =
|
||||||
|
SHADER_VERSION
|
||||||
|
"#if (__VERSION__ > 120) \n"
|
||||||
|
"# define IN in \n"
|
||||||
|
"# define OUT out \n"
|
||||||
|
"# define texture2D texture \n"
|
||||||
|
"#else \n"
|
||||||
|
"# define IN varying \n"
|
||||||
|
"# define OUT \n"
|
||||||
|
"#endif // __VERSION __ \n"
|
||||||
|
"IN mediump vec2 texpos; \n"
|
||||||
|
"uniform sampler2D uTex; \n"
|
||||||
|
"uniform lowp vec4 uColor; \n"
|
||||||
|
"OUT lowp vec4 fragColor; \n"
|
||||||
|
"void main(void) { \n"
|
||||||
|
" fragColor = texture2D(uTex, texpos).r * uColor; \n"
|
||||||
|
#ifdef GLES2
|
||||||
|
" gl_FragColor = fragColor; \n"
|
||||||
|
#endif
|
||||||
|
"} \n"
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The atlas struct holds a texture that contains the visible US-ASCII characters
|
||||||
|
* of a certain font rendered with a certain character height.
|
||||||
|
* It also contains an array that contains all the information necessary to
|
||||||
|
* generate the appropriate vertex and texture coordinates for each character.
|
||||||
|
*
|
||||||
|
* After the constructor is run, you don't need to use any FreeType functions anymore.
|
||||||
|
*/
|
||||||
|
struct Atlas {
|
||||||
|
GLuint tex; // texture object
|
||||||
|
|
||||||
|
int w; // width of texture in pixels
|
||||||
|
int h; // height of texture in pixels
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float ax; // advance.x
|
||||||
|
float ay; // advance.y
|
||||||
|
|
||||||
|
float bw; // bitmap.width;
|
||||||
|
float bh; // bitmap.height;
|
||||||
|
|
||||||
|
float bl; // bitmap_left;
|
||||||
|
float bt; // bitmap_top;
|
||||||
|
|
||||||
|
float tx; // x offset of glyph in texture coordinates
|
||||||
|
float ty; // y offset of glyph in texture coordinates
|
||||||
|
} c[128]; // character information
|
||||||
|
|
||||||
|
Atlas(FT_Face face, int height) {
|
||||||
|
FT_Set_Pixel_Sizes(face, 0, height);
|
||||||
|
FT_GlyphSlot g = face->glyph;
|
||||||
|
|
||||||
|
int roww = 0;
|
||||||
|
int rowh = 0;
|
||||||
|
w = 0;
|
||||||
|
h = 0;
|
||||||
|
|
||||||
|
memset(c, 0, sizeof c);
|
||||||
|
|
||||||
|
/* Find minimum size for a texture holding all visible ASCII characters */
|
||||||
|
for (int i = 32; i < 128; i++) {
|
||||||
|
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
|
||||||
|
fprintf(stderr, "Loading character %c failed!\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (roww + g->bitmap.width + 1 >= MAXWIDTH) {
|
||||||
|
w = std::max(w, roww);
|
||||||
|
h += rowh;
|
||||||
|
roww = 0;
|
||||||
|
rowh = 0;
|
||||||
|
}
|
||||||
|
roww += g->bitmap.width + 1;
|
||||||
|
rowh = std::max(rowh, (int)g->bitmap.rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
w = std::max(w, roww);
|
||||||
|
h += rowh;
|
||||||
|
|
||||||
|
/* Create a texture that will be used to hold all ASCII glyphs */
|
||||||
|
|
||||||
|
graphics::ObjectHandle texHandle = gfxContext.createTexture(graphics::target::TEXTURE_2D);
|
||||||
|
tex = GLuint(texHandle);
|
||||||
|
|
||||||
|
graphics::Context::InitTextureParams initParams;
|
||||||
|
initParams.handle = texHandle;
|
||||||
|
initParams.width = w;
|
||||||
|
initParams.height = h;
|
||||||
|
initParams.internalFormat = monohromeInternalformat;
|
||||||
|
initParams.format = monohromeformat;
|
||||||
|
initParams.dataType = graphics::datatype::UNSIGNED_BYTE;
|
||||||
|
gfxContext.init2DTexture(initParams);
|
||||||
|
|
||||||
|
/* We require 1 byte alignment when uploading texture data */
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
graphics::Context::TexParameters setParams;
|
||||||
|
setParams.handle = texHandle;
|
||||||
|
setParams.target = graphics::target::TEXTURE_2D;
|
||||||
|
setParams.minFilter = graphics::textureParameters::FILTER_LINEAR;
|
||||||
|
setParams.magFilter = graphics::textureParameters::FILTER_LINEAR;
|
||||||
|
setParams.wrapS = graphics::textureParameters::WRAP_CLAMP_TO_EDGE;
|
||||||
|
setParams.wrapT = graphics::textureParameters::WRAP_CLAMP_TO_EDGE;
|
||||||
|
gfxContext.setTextureParameters(setParams);
|
||||||
|
|
||||||
|
/* Paste all glyph bitmaps into the texture, remembering the offset */
|
||||||
|
int ox = 0;
|
||||||
|
int oy = 0;
|
||||||
|
|
||||||
|
rowh = 0;
|
||||||
|
|
||||||
|
for (int i = 32; i < 128; i++) {
|
||||||
|
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
|
||||||
|
fprintf(stderr, "Loading character %c failed!\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ox + g->bitmap.width + 1 >= MAXWIDTH) {
|
||||||
|
oy += rowh;
|
||||||
|
rowh = 0;
|
||||||
|
ox = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, monohromeformat, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||||
|
c[i].ax = _FIXED2FLOAT(g->advance.x, 6);
|
||||||
|
c[i].ay = _FIXED2FLOAT(g->advance.y, 6);
|
||||||
|
|
||||||
|
c[i].bw = (float)g->bitmap.width;
|
||||||
|
c[i].bh = (float)g->bitmap.rows;
|
||||||
|
|
||||||
|
c[i].bl = (float)g->bitmap_left;
|
||||||
|
c[i].bt = (float)g->bitmap_top;
|
||||||
|
|
||||||
|
c[i].tx = ox / (float)w;
|
||||||
|
c[i].ty = oy / (float)h;
|
||||||
|
|
||||||
|
rowh = std::max(rowh, (int)g->bitmap.rows);
|
||||||
|
ox += g->bitmap.width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Atlas() {
|
||||||
|
gfxContext.deleteTexture(graphics::ObjectHandle(tex));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TextDrawer::TextDrawer() :
|
||||||
|
m_pAtlas(nullptr), m_program(0), m_uTex(0), m_uColor(0), m_vbo(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TextDrawer & TextDrawer::get() {
|
||||||
|
static TextDrawer drawer;
|
||||||
|
return drawer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool getFontFileName(char * _strName)
|
||||||
|
{
|
||||||
|
#ifdef OS_WINDOWS
|
||||||
|
char * pSysPath = getenv("WINDIR");
|
||||||
|
if (pSysPath == nullptr)
|
||||||
|
return false;
|
||||||
|
sprintf(_strName, "%s/Fonts/%s", pSysPath, config.font.name.c_str());
|
||||||
|
#elif defined (ANDROID)
|
||||||
|
sprintf(_strName, "/system/fonts/%s", config.font.name.c_str());
|
||||||
|
#elif defined (PANDORA)
|
||||||
|
sprintf(_strName, "/usr/share/fonts/truetype/%s", config.font.name.c_str());
|
||||||
|
#else
|
||||||
|
sprintf(_strName, "/usr/share/fonts/truetype/freefont/%s", config.font.name.c_str());
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Library ft;
|
||||||
|
FT_Face face;
|
||||||
|
|
||||||
|
void TextDrawer::init()
|
||||||
|
{
|
||||||
|
if (m_pAtlas != nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char strBuffer[PLUGIN_PATH_SIZE];
|
||||||
|
const char *fontfilename;
|
||||||
|
if (getFontFileName(strBuffer))
|
||||||
|
fontfilename = strBuffer;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initialize the FreeType2 library */
|
||||||
|
if (FT_Init_FreeType(&ft)) {
|
||||||
|
fprintf(stderr, "Could not init freetype library\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load a font */
|
||||||
|
if (FT_New_Face(ft, fontfilename, 0, &face)) {
|
||||||
|
fprintf(stderr, "Could not open font %s\n", fontfilename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_program = createRectShaderProgram(strDrawTextVertexShader, strDrawTextFragmentShader);
|
||||||
|
if(m_program == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_uTex = glGetUniformLocation(m_program, "uTex");
|
||||||
|
m_uColor = glGetUniformLocation(m_program, "uColor");
|
||||||
|
|
||||||
|
if(m_uTex == -1 || m_uColor == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Create the vertex buffer object
|
||||||
|
glGenBuffers(1, &m_vbo);
|
||||||
|
|
||||||
|
/* Create texture atlas for selected font size */
|
||||||
|
m_pAtlas = new Atlas(face, config.font.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextDrawer::destroy()
|
||||||
|
{
|
||||||
|
if (m_pAtlas == nullptr)
|
||||||
|
return;
|
||||||
|
delete m_pAtlas;
|
||||||
|
m_pAtlas = nullptr;
|
||||||
|
glDeleteBuffers(1, &m_vbo);
|
||||||
|
m_vbo = 0;
|
||||||
|
glDeleteProgram(m_program);
|
||||||
|
m_program = 0;
|
||||||
|
FT_Done_Face(face);
|
||||||
|
FT_Done_FreeType(ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render text using the currently loaded font and currently set font size.
|
||||||
|
* Rendering starts at coordinates (x, y), z is always 0.
|
||||||
|
* The pixel coordinates that the FreeType2 library uses are scaled by (sx, sy).
|
||||||
|
*/
|
||||||
|
void TextDrawer::renderText(const char *_pText, float _x, float _y) const
|
||||||
|
{
|
||||||
|
if (m_pAtlas == nullptr)
|
||||||
|
return;
|
||||||
|
OGLVideo & ogl = video();
|
||||||
|
const float sx = 2.0f / ogl.getWidth();
|
||||||
|
const float sy = 2.0f / ogl.getHeight();
|
||||||
|
|
||||||
|
const u8 *p;
|
||||||
|
|
||||||
|
glUseProgram(m_program);
|
||||||
|
|
||||||
|
/* Enable blending, necessary for our alpha texture */
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
|
/* Set color */
|
||||||
|
glUniform4fv(m_uColor, 1, config.font.colorf);
|
||||||
|
|
||||||
|
/* Use the texture containing the atlas */
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_pAtlas->tex);
|
||||||
|
glUniform1i(m_uTex, 0);
|
||||||
|
|
||||||
|
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);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
#ifndef GLES2
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set up the VBO for our vertex data */
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||||
|
glVertexAttribPointer(SC_RECT_POSITION, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
|
||||||
|
std::vector<point> coords(6 * strlen(_pText));
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
/* Loop through all characters */
|
||||||
|
for (p = (const u8 *)_pText; *p; ++p) {
|
||||||
|
/* Calculate the vertex and texture coordinates */
|
||||||
|
float x2 = _x + m_pAtlas->c[*p].bl * sx;
|
||||||
|
float y2 = -_y - m_pAtlas->c[*p].bt * sy;
|
||||||
|
float w = m_pAtlas->c[*p].bw * sx;
|
||||||
|
float h = m_pAtlas->c[*p].bh * sy;
|
||||||
|
|
||||||
|
/* Advance the cursor to the start of the next character */
|
||||||
|
_x += m_pAtlas->c[*p].ax * sx;
|
||||||
|
_y += m_pAtlas->c[*p].ay * sy;
|
||||||
|
|
||||||
|
/* Skip glyphs that have no pixels */
|
||||||
|
if (!w || !h)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
coords[c++] = point(x2, -y2, m_pAtlas->c[*p].tx, m_pAtlas->c[*p].ty);
|
||||||
|
coords[c++] = point(x2 + w, -y2, m_pAtlas->c[*p].tx + m_pAtlas->c[*p].bw / m_pAtlas->w, m_pAtlas->c[*p].ty);
|
||||||
|
coords[c++] = point(x2, -y2 - h, m_pAtlas->c[*p].tx, m_pAtlas->c[*p].ty + m_pAtlas->c[*p].bh / m_pAtlas->h);
|
||||||
|
coords[c++] = point(x2 + w, -y2, m_pAtlas->c[*p].tx + m_pAtlas->c[*p].bw / m_pAtlas->w, m_pAtlas->c[*p].ty);
|
||||||
|
coords[c++] = point(x2, -y2 - h, m_pAtlas->c[*p].tx, m_pAtlas->c[*p].ty + m_pAtlas->c[*p].bh / m_pAtlas->h);
|
||||||
|
coords[c++] = point(x2 + w, -y2 - h, m_pAtlas->c[*p].tx + m_pAtlas->c[*p].bw / m_pAtlas->w, m_pAtlas->c[*p].ty + m_pAtlas->c[*p].bh / m_pAtlas->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw all the character on the screen in one go */
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, coords.size()*sizeof(point), coords.data(), GL_DYNAMIC_DRAW);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, c);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextDrawer::getTextSize(const char *_pText, float & _w, float & _h) const
|
||||||
|
{
|
||||||
|
_w = _h = 0;
|
||||||
|
if (m_pAtlas == nullptr)
|
||||||
|
return;
|
||||||
|
OGLVideo & ogl = video();
|
||||||
|
const float sx = 2.0f / ogl.getWidth();
|
||||||
|
const float sy = 2.0f / ogl.getHeight();
|
||||||
|
float bw, bh;
|
||||||
|
|
||||||
|
for (const u8 *p = (const u8 *)_pText; *p; ++p) {
|
||||||
|
bw = m_pAtlas->c[*p].bw * sx;
|
||||||
|
bh = m_pAtlas->c[*p].bh * sy;
|
||||||
|
|
||||||
|
_w += m_pAtlas->c[*p].ax * sx;
|
||||||
|
_h += m_pAtlas->c[*p].ay * sy;
|
||||||
|
}
|
||||||
|
_w += bw;
|
||||||
|
_h += bh;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <Config.h>
|
||||||
#include "GLFunctions.h"
|
#include "GLFunctions.h"
|
||||||
#include "opengl_Attributes.h"
|
#include "opengl_Attributes.h"
|
||||||
#include "opengl_CachedFunctions.h"
|
#include "opengl_CachedFunctions.h"
|
||||||
|
@ -5,8 +6,9 @@
|
||||||
|
|
||||||
using namespace opengl;
|
using namespace opengl;
|
||||||
|
|
||||||
UnbufferedDrawer::UnbufferedDrawer(CachedVertexAttribArray * _cachedAttribArray)
|
UnbufferedDrawer::UnbufferedDrawer(const GLInfo & _glinfo, CachedVertexAttribArray * _cachedAttribArray)
|
||||||
: m_cachedAttribArray(_cachedAttribArray)
|
: m_glInfo(_glinfo)
|
||||||
|
, m_cachedAttribArray(_cachedAttribArray)
|
||||||
{
|
{
|
||||||
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::position, false);
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::position, false);
|
||||||
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::color, false);
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::color, false);
|
||||||
|
@ -37,6 +39,9 @@ bool UnbufferedDrawer::_updateAttribPointer(u32 _index, const void * _ptr)
|
||||||
|
|
||||||
void UnbufferedDrawer::drawTriangles(const DrawTriangleParameters & _params)
|
void UnbufferedDrawer::drawTriangles(const DrawTriangleParameters & _params)
|
||||||
{
|
{
|
||||||
|
if (m_glInfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0)
|
||||||
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
|
|
||||||
{
|
{
|
||||||
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::position, true);
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::position, true);
|
||||||
const void * ptr = &_params.vertices->x;
|
const void * ptr = &_params.vertices->x;
|
||||||
|
@ -100,7 +105,7 @@ void UnbufferedDrawer::drawRects(const DrawRectParameters & _params)
|
||||||
|
|
||||||
{
|
{
|
||||||
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::color, true);
|
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::color, true);
|
||||||
glVertexAttrib4fv(rectAttrib::color, _params.rectColor);
|
glVertexAttrib4fv(rectAttrib::color, _params.rectColor.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_params.combiner->usesTile(0)) {
|
if (_params.combiner->usesTile(0)) {
|
||||||
|
@ -127,3 +132,32 @@ void UnbufferedDrawer::drawRects(const DrawRectParameters & _params)
|
||||||
|
|
||||||
glDrawArrays(GLenum(_params.mode), 0, _params.verticesCount);
|
glDrawArrays(GLenum(_params.mode), 0, _params.verticesCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnbufferedDrawer::drawLine(f32 _width, SPVertex * _vertices)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::position, true);
|
||||||
|
const void * ptr = &_vertices->x;
|
||||||
|
if (_updateAttribPointer(triangleAttrib::position, ptr))
|
||||||
|
glVertexAttribPointer(triangleAttrib::position, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::color, true);
|
||||||
|
const void * ptr = &_vertices->r;
|
||||||
|
if (_updateAttribPointer(triangleAttrib::color, ptr))
|
||||||
|
glVertexAttribPointer(triangleAttrib::color, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::texcoord, false);
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::numlights, false);
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(triangleAttrib::modify, false);
|
||||||
|
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::position, false);
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::color, false);
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::texcoord0, false);
|
||||||
|
m_cachedAttribArray->enableVertexAttribArray(rectAttrib::texcoord1, false);
|
||||||
|
|
||||||
|
glLineWidth(_width);
|
||||||
|
glDrawArrays(GL_LINES, 0, 2);
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <Graphics/DrawerImpl.h>
|
#include <Graphics/GraphicsDrawerImpl.h>
|
||||||
|
#include "opengl_GLInfo.h"
|
||||||
|
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
class CachedVertexAttribArray;
|
class CachedVertexAttribArray;
|
||||||
|
@ -8,16 +9,19 @@ namespace opengl {
|
||||||
class UnbufferedDrawer : public graphics::DrawerImpl
|
class UnbufferedDrawer : public graphics::DrawerImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UnbufferedDrawer(CachedVertexAttribArray * _cachedAttribArray);
|
UnbufferedDrawer(const GLInfo & _glinfo, CachedVertexAttribArray * _cachedAttribArray);
|
||||||
~UnbufferedDrawer();
|
~UnbufferedDrawer();
|
||||||
|
|
||||||
void drawTriangles(const DrawTriangleParameters & _params) override;
|
void drawTriangles(const DrawTriangleParameters & _params) override;
|
||||||
|
|
||||||
void drawRects(const DrawRectParameters & _params) override;
|
void drawRects(const DrawRectParameters & _params) override;
|
||||||
|
|
||||||
|
void drawLine(f32 _width, SPVertex * _vertices) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _updateAttribPointer(u32 _index, const void * _ptr);
|
bool _updateAttribPointer(u32 _index, const void * _ptr);
|
||||||
|
|
||||||
|
const GLInfo & m_glInfo;
|
||||||
CachedVertexAttribArray * m_cachedAttribArray;
|
CachedVertexAttribArray * m_cachedAttribArray;
|
||||||
std::array<const void*, MaxAttribIndex> m_attribsData;
|
std::array<const void*, MaxAttribIndex> m_attribsData;
|
||||||
};
|
};
|
||||||
|
|
16
src/Graphics/TextDrawerImpl.h
Normal file
16
src/Graphics/TextDrawerImpl.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef TEXTDRAWERIMPL_H
|
||||||
|
#define TEXTDRAWERIMPL_H
|
||||||
|
|
||||||
|
namespace graphics {
|
||||||
|
|
||||||
|
class TextDrawer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~TextDrawer() {}
|
||||||
|
virtual void renderText(const char *_pText, float x, float y) const = 0;
|
||||||
|
virtual void getTextSize(const char *_pText, float & _w, float & _h) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TEXTDRAWERIMPL_H
|
|
@ -4,13 +4,15 @@
|
||||||
#include "Graphics/Parameters.h"
|
#include "Graphics/Parameters.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "RSP.h"
|
#include "RSP.h"
|
||||||
|
#include "RDP.h"
|
||||||
#include "VI.h"
|
#include "VI.h"
|
||||||
#include "FrameBuffer.h"
|
#include "FrameBuffer.h"
|
||||||
#include "DepthBuffer.h"
|
#include "DepthBuffer.h"
|
||||||
#include "DisplayWindow.h"
|
#include "DisplayWindow.h"
|
||||||
#include "SoftwareRender.h"
|
#include "SoftwareRender.h"
|
||||||
#include "Graphics/DrawerImpl.h"
|
#include "Graphics/GraphicsDrawerImpl.h"
|
||||||
#include "GraphicsDrawer.h"
|
#include "GraphicsDrawer.h"
|
||||||
|
#include "Performance.h"
|
||||||
|
|
||||||
using namespace graphics;
|
using namespace graphics;
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ GraphicsDrawer::GraphicsDrawer()
|
||||||
, m_bImageTexture(false)
|
, m_bImageTexture(false)
|
||||||
, m_bFlatColors(false)
|
, m_bFlatColors(false)
|
||||||
, m_drawerImpl(gfxContext.createDrawerImpl())
|
, m_drawerImpl(gfxContext.createDrawerImpl())
|
||||||
|
, m_textDrawer(gfxContext.createTextDrawer())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,12 +603,9 @@ void GraphicsDrawer::_updateStates(DrawingState _drawingState) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsDrawer::_prepareDrawTriangle(bool _dma)
|
void GraphicsDrawer::_prepareDrawTriangle()
|
||||||
{
|
{
|
||||||
#ifdef GL_IMAGE_TEXTURES_SUPPORT
|
m_texrectDrawer.draw();
|
||||||
if (m_bImageTexture && config.frameBufferEmulation.N64DepthCompare != 0)
|
|
||||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
|
||||||
#endif // GL_IMAGE_TEXTURES_SUPPORT
|
|
||||||
|
|
||||||
if ((m_modifyVertices & MODIFY_XY) != 0)
|
if ((m_modifyVertices & MODIFY_XY) != 0)
|
||||||
gSP.changed &= ~CHANGED_VIEWPORT;
|
gSP.changed &= ~CHANGED_VIEWPORT;
|
||||||
|
@ -614,7 +614,6 @@ void GraphicsDrawer::_prepareDrawTriangle(bool _dma)
|
||||||
_updateStates(DrawingState::Triangle);
|
_updateStates(DrawingState::Triangle);
|
||||||
|
|
||||||
m_drawingState = DrawingState::Triangle;
|
m_drawingState = DrawingState::Triangle;
|
||||||
m_bDmaVertices = _dma;
|
|
||||||
|
|
||||||
bool bFlatColors = false;
|
bool bFlatColors = false;
|
||||||
if (!RSP.bLLE && (gSP.geometryMode & G_LIGHTING) == 0) {
|
if (!RSP.bLLE && (gSP.geometryMode & G_LIGHTING) == 0) {
|
||||||
|
@ -641,17 +640,18 @@ void GraphicsDrawer::drawTriangles()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_prepareDrawTriangle(false);
|
_prepareDrawTriangle();
|
||||||
|
|
||||||
DrawerImpl::DrawTriangleParameters triPapams;
|
DrawerImpl::DrawTriangleParameters triParams;
|
||||||
triPapams.mode = drawmode::TRIANGLES;
|
triParams.mode = drawmode::TRIANGLES;
|
||||||
triPapams.elementsType = datatype::UNSIGNED_BYTE;
|
triParams.flatColors = m_bFlatColors;
|
||||||
triPapams.verticesCount = static_cast<u32>(triangles.maxElement) + 1;
|
triParams.elementsType = datatype::UNSIGNED_BYTE;
|
||||||
triPapams.elementsCount = triangles.num;
|
triParams.verticesCount = static_cast<u32>(triangles.maxElement) + 1;
|
||||||
triPapams.vertices = triangles.vertices.data();
|
triParams.elementsCount = triangles.num;
|
||||||
triPapams.elements = triangles.elements.data();
|
triParams.vertices = triangles.vertices.data();
|
||||||
triPapams.combiner = currentCombiner();
|
triParams.elements = triangles.elements.data();
|
||||||
m_drawerImpl->drawTriangles(triPapams);
|
triParams.combiner = currentCombiner();
|
||||||
|
m_drawerImpl->drawTriangles(triParams);
|
||||||
|
|
||||||
if (config.frameBufferEmulation.enable != 0 &&
|
if (config.frameBufferEmulation.enable != 0 &&
|
||||||
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||||
|
@ -665,3 +665,730 @@ void GraphicsDrawer::drawTriangles()
|
||||||
triangles.num = 0;
|
triangles.num = 0;
|
||||||
triangles.maxElement = 0;
|
triangles.maxElement = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawScreenSpaceTriangle(u32 _numVtx)
|
||||||
|
{
|
||||||
|
if (_numVtx == 0 || !_canDraw())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < _numVtx; ++i) {
|
||||||
|
SPVertex & vtx = m_dmaVertices[i];
|
||||||
|
vtx.modify = MODIFY_ALL;
|
||||||
|
}
|
||||||
|
m_modifyVertices = MODIFY_ALL;
|
||||||
|
|
||||||
|
gSP.changed &= ~CHANGED_GEOMETRYMODE; // Don't update cull mode
|
||||||
|
_prepareDrawTriangle();
|
||||||
|
gfxContext.enable(enable::CULL_FACE, false);
|
||||||
|
|
||||||
|
DrawerImpl::DrawTriangleParameters triParams;
|
||||||
|
triParams.mode = drawmode::TRIANGLE_STRIP;
|
||||||
|
triParams.flatColors = m_bFlatColors;
|
||||||
|
triParams.verticesCount = _numVtx;
|
||||||
|
triParams.vertices = m_dmaVertices.data();
|
||||||
|
triParams.combiner = currentCombiner();
|
||||||
|
m_drawerImpl->drawTriangles(triParams);
|
||||||
|
|
||||||
|
frameBufferList().setBufferChanged();
|
||||||
|
gSP.changed |= CHANGED_GEOMETRYMODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
|
||||||
|
{
|
||||||
|
if (_numVtx == 0 || !_canDraw())
|
||||||
|
return;
|
||||||
|
_prepareDrawTriangle();
|
||||||
|
|
||||||
|
|
||||||
|
DrawerImpl::DrawTriangleParameters triParams;
|
||||||
|
triParams.mode = drawmode::TRIANGLES;
|
||||||
|
triParams.flatColors = m_bFlatColors;
|
||||||
|
triParams.verticesCount = _numVtx;
|
||||||
|
triParams.vertices = m_dmaVertices.data();
|
||||||
|
triParams.combiner = currentCombiner();
|
||||||
|
m_drawerImpl->drawTriangles(triParams);
|
||||||
|
|
||||||
|
if (config.frameBufferEmulation.enable != 0 &&
|
||||||
|
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||||
|
gDP.otherMode.depthUpdate != 0) {
|
||||||
|
renderTriangles(m_dmaVertices.data(), nullptr, _numVtx);
|
||||||
|
FrameBuffer * pCurrentDepthBuffer = frameBufferList().findBuffer(gDP.depthImageAddress);
|
||||||
|
if (pCurrentDepthBuffer != nullptr)
|
||||||
|
pCurrentDepthBuffer->m_cleared = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::_drawThickLine(int _v0, int _v1, float _width)
|
||||||
|
{
|
||||||
|
if ((gSP.geometryMode & G_LIGHTING) == 0) {
|
||||||
|
if ((gSP.geometryMode & G_SHADE) == 0) {
|
||||||
|
SPVertex & vtx1 = triangles.vertices[_v0];
|
||||||
|
vtx1.flat_r = gDP.primColor.r;
|
||||||
|
vtx1.flat_g = gDP.primColor.g;
|
||||||
|
vtx1.flat_b = gDP.primColor.b;
|
||||||
|
vtx1.flat_a = gDP.primColor.a;
|
||||||
|
SPVertex & vtx2 = triangles.vertices[_v1];
|
||||||
|
vtx2.flat_r = gDP.primColor.r;
|
||||||
|
vtx2.flat_g = gDP.primColor.g;
|
||||||
|
vtx2.flat_b = gDP.primColor.b;
|
||||||
|
vtx2.flat_a = gDP.primColor.a;
|
||||||
|
}
|
||||||
|
else if ((gSP.geometryMode & G_SHADING_SMOOTH) == 0) {
|
||||||
|
// Flat shading
|
||||||
|
SPVertex & vtx0 = triangles.vertices[_v0 + ((RSP.w1 >> 24) & 3)];
|
||||||
|
SPVertex & vtx1 = triangles.vertices[_v0];
|
||||||
|
vtx1.r = vtx1.flat_r = vtx0.r;
|
||||||
|
vtx1.g = vtx1.flat_g = vtx0.g;
|
||||||
|
vtx1.b = vtx1.flat_b = vtx0.b;
|
||||||
|
vtx1.a = vtx1.flat_a = vtx0.a;
|
||||||
|
SPVertex & vtx2 = triangles.vertices[_v1];
|
||||||
|
vtx2.r = vtx2.flat_r = vtx0.r;
|
||||||
|
vtx2.g = vtx2.flat_g = vtx0.g;
|
||||||
|
vtx2.b = vtx2.flat_b = vtx0.b;
|
||||||
|
vtx2.a = vtx2.flat_a = vtx0.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDMAVerticesSize(4);
|
||||||
|
SPVertex * pVtx = getDMAVerticesData();
|
||||||
|
pVtx[0] = triangles.vertices[_v0];
|
||||||
|
pVtx[0].x = pVtx[0].x / pVtx[0].w * gSP.viewport.vscale[0] + gSP.viewport.vtrans[0];
|
||||||
|
pVtx[0].y = pVtx[0].y / pVtx[0].w * gSP.viewport.vscale[1] + gSP.viewport.vtrans[1];
|
||||||
|
pVtx[0].z = pVtx[0].z / pVtx[0].w * gSP.viewport.vscale[2] + gSP.viewport.vtrans[2];
|
||||||
|
pVtx[1] = pVtx[0];
|
||||||
|
|
||||||
|
pVtx[2] = triangles.vertices[_v1];
|
||||||
|
pVtx[2].x = pVtx[2].x / pVtx[2].w * gSP.viewport.vscale[0] + gSP.viewport.vtrans[0];
|
||||||
|
pVtx[2].y = pVtx[2].y / pVtx[2].w * gSP.viewport.vscale[1] + gSP.viewport.vtrans[1];
|
||||||
|
pVtx[2].z = pVtx[2].z / pVtx[2].w * gSP.viewport.vscale[2] + gSP.viewport.vtrans[2];
|
||||||
|
pVtx[3] = pVtx[2];
|
||||||
|
|
||||||
|
if (fabs(pVtx[0].y - pVtx[2].y) < 0.0001) {
|
||||||
|
const f32 Y = pVtx[0].y;
|
||||||
|
pVtx[0].y = pVtx[2].y = Y - _width;
|
||||||
|
pVtx[1].y = pVtx[3].y = Y + _width;
|
||||||
|
}
|
||||||
|
else if (fabs(pVtx[0].x - pVtx[2].x) < 0.0001) {
|
||||||
|
const f32 X = pVtx[0].x;
|
||||||
|
pVtx[0].x = pVtx[2].x = X - _width;
|
||||||
|
pVtx[1].x = pVtx[3].x = X + _width;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const f32 X0 = pVtx[0].x;
|
||||||
|
const f32 Y0 = pVtx[0].y;
|
||||||
|
const f32 X1 = pVtx[2].x;
|
||||||
|
const f32 Y1 = pVtx[2].y;
|
||||||
|
const f32 dx = X1 - X0;
|
||||||
|
const f32 dy = Y1 - Y0;
|
||||||
|
const f32 len = sqrtf(dx*dx + dy*dy);
|
||||||
|
const f32 wx = dy * _width / len;
|
||||||
|
const f32 wy = dx * _width / len;
|
||||||
|
pVtx[0].x = X0 + wx;
|
||||||
|
pVtx[0].y = Y0 - wy;
|
||||||
|
pVtx[1].x = X0 - wx;
|
||||||
|
pVtx[1].y = Y0 + wy;
|
||||||
|
pVtx[2].x = X1 + wx;
|
||||||
|
pVtx[2].y = Y1 - wy;
|
||||||
|
pVtx[3].x = X1 - wx;
|
||||||
|
pVtx[3].y = Y1 + wy;
|
||||||
|
}
|
||||||
|
drawScreenSpaceTriangle(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawLine(int _v0, int _v1, float _width)
|
||||||
|
{
|
||||||
|
m_texrectDrawer.draw();
|
||||||
|
|
||||||
|
if (!_canDraw())
|
||||||
|
return;
|
||||||
|
|
||||||
|
GLfloat lineWidth = _width;
|
||||||
|
if (config.frameBufferEmulation.nativeResFactor == 0)
|
||||||
|
lineWidth *= video().getScaleX();
|
||||||
|
else
|
||||||
|
lineWidth *= config.frameBufferEmulation.nativeResFactor;
|
||||||
|
if (lineWidth > m_maxLineWidth) {
|
||||||
|
_drawThickLine(_v0, _v1, _width * 0.5f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((triangles.vertices[_v0].modify & MODIFY_XY) != 0)
|
||||||
|
gSP.changed &= ~CHANGED_VIEWPORT;
|
||||||
|
if (gSP.changed || gDP.changed)
|
||||||
|
_updateStates(DrawingState::Line);
|
||||||
|
|
||||||
|
m_drawingState = DrawingState::Line;
|
||||||
|
|
||||||
|
if ((triangles.vertices[_v0].modify & MODIFY_XY) != 0)
|
||||||
|
_updateScreenCoordsViewport();
|
||||||
|
|
||||||
|
SPVertex vertexBuf[2] = { triangles.vertices[triangles.elements[_v0]], triangles.vertices[triangles.elements[_v1]] };
|
||||||
|
m_drawerImpl->drawLine(lineWidth, vertexBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry, float *_pColor)
|
||||||
|
{
|
||||||
|
m_texrectDrawer.draw();
|
||||||
|
|
||||||
|
if (!_canDraw())
|
||||||
|
return;
|
||||||
|
|
||||||
|
gSP.changed &= ~CHANGED_GEOMETRYMODE; // Don't update cull mode
|
||||||
|
if (gSP.changed || gDP.changed)
|
||||||
|
_updateStates(DrawingState::Rect);
|
||||||
|
|
||||||
|
m_drawingState = DrawingState::Rect;
|
||||||
|
|
||||||
|
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
|
||||||
|
OGLVideo & ogl = video();
|
||||||
|
if (pCurrentBuffer == nullptr)
|
||||||
|
gfxContext.setViewport(0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight());
|
||||||
|
else
|
||||||
|
gfxContext.setViewport(0, 0, pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX, pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY);
|
||||||
|
|
||||||
|
gfxContext.enable(enable::CULL_FACE, false);
|
||||||
|
|
||||||
|
const float scaleX = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_width : VI.rwidth;
|
||||||
|
const float scaleY = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_height : VI.rheight;
|
||||||
|
const float Z = (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : 0.0f;
|
||||||
|
const float W = 1.0f;
|
||||||
|
m_rect[0].x = (float)_ulx * (2.0f * scaleX) - 1.0;
|
||||||
|
m_rect[0].y = (float)_uly * (-2.0f * scaleY) + 1.0;
|
||||||
|
m_rect[0].z = Z;
|
||||||
|
m_rect[0].w = W;
|
||||||
|
m_rect[1].x = (float)_lrx * (2.0f * scaleX) - 1.0;
|
||||||
|
m_rect[1].y = m_rect[0].y;
|
||||||
|
m_rect[1].z = Z;
|
||||||
|
m_rect[1].w = W;
|
||||||
|
m_rect[2].x = m_rect[0].x;
|
||||||
|
m_rect[2].y = (float)_lry * (-2.0f * scaleY) + 1.0;
|
||||||
|
m_rect[2].z = Z;
|
||||||
|
m_rect[2].w = W;
|
||||||
|
m_rect[3].x = m_rect[1].x;
|
||||||
|
m_rect[3].y = m_rect[2].y;
|
||||||
|
m_rect[3].z = Z;
|
||||||
|
m_rect[3].w = W;
|
||||||
|
|
||||||
|
if (ogl.isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100) && (_lrx - _ulx < VI.width * 9 / 10)) {
|
||||||
|
const float scale = ogl.getAdjustScale();
|
||||||
|
for (u32 i = 0; i < 4; ++i)
|
||||||
|
m_rect[i].x *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::DrawerImpl::DrawRectParameters rectParams;
|
||||||
|
rectParams.mode = drawmode::TRIANGLE_STRIP;
|
||||||
|
if (gDP.otherMode.cycleType == G_CYC_FILL)
|
||||||
|
std::copy_n(_pColor, sizeof(_pColor[0]) * 4, rectParams.rectColor.data());
|
||||||
|
else
|
||||||
|
rectParams.rectColor.fill(0.0f);
|
||||||
|
rectParams.verticesCount = 4;
|
||||||
|
rectParams.vertices = m_rect;
|
||||||
|
rectParams.combiner = currentCombiner();
|
||||||
|
m_drawerImpl->drawRects(rectParams);
|
||||||
|
gSP.changed |= CHANGED_GEOMETRYMODE | CHANGED_VIEWPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool texturedRectShadowMap(const GraphicsDrawer::TexturedRectParams &)
|
||||||
|
{
|
||||||
|
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
|
||||||
|
if (pCurrentBuffer != nullptr) {
|
||||||
|
if (gDP.textureImage.size == 2 && gDP.textureImage.address >= gDP.depthImageAddress && gDP.textureImage.address < (gDP.depthImageAddress + gDP.colorImage.width*gDP.colorImage.width * 6 / 4)) {
|
||||||
|
#ifdef GL_IMAGE_TEXTURES_SUPPORT
|
||||||
|
if (video().getRender().isImageTexturesSupported()) {
|
||||||
|
pCurrentBuffer->m_pDepthBuffer->activateDepthBufferTexture(pCurrentBuffer);
|
||||||
|
CombinerInfo::get().setDepthFogCombiner();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//u32 rectDepthBufferCopyFrame = 0xFFFFFFFF;
|
||||||
|
static
|
||||||
|
bool texturedRectDepthBufferCopy(const GraphicsDrawer::TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
// Copy one line from depth buffer into auxiliary color buffer with height = 1.
|
||||||
|
// Data from depth buffer loaded into TMEM and then rendered to RDRAM by texrect.
|
||||||
|
// Works only with depth buffer emulation enabled.
|
||||||
|
// Load of arbitrary data to that area causes weird camera rotation in CBFD.
|
||||||
|
const gDPTile * pTile = gSP.textureTile[0];
|
||||||
|
if (pTile->loadType == LOADTYPE_BLOCK && gDP.textureImage.size == 2 && gDP.textureImage.address >= gDP.depthImageAddress && gDP.textureImage.address < (gDP.depthImageAddress + gDP.colorImage.width*gDP.colorImage.width * 6 / 4)) {
|
||||||
|
if (config.frameBufferEmulation.copyDepthToRDRAM == Config::cdDisable)
|
||||||
|
return true;
|
||||||
|
FrameBuffer * pBuffer = frameBufferList().getCurrent();
|
||||||
|
if (pBuffer == nullptr)
|
||||||
|
return true;
|
||||||
|
pBuffer->m_cleared = true;
|
||||||
|
if (config.frameBufferEmulation.copyDepthToRDRAM == Config::cdCopyFromVRam) {
|
||||||
|
if (rectDepthBufferCopyFrame != video().getBuffersSwapCount()) {
|
||||||
|
rectDepthBufferCopyFrame = video().getBuffersSwapCount();
|
||||||
|
if (!FrameBuffer_CopyDepthBuffer(gDP.colorImage.address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
RDP_RepeatLastLoadBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 width = (u32)(_params.lrx - _params.ulx);
|
||||||
|
const u32 ulx = (u32)_params.ulx;
|
||||||
|
u16 * pSrc = ((u16*)TMEM) + (u32)floorf(_params.uls + 0.5f);
|
||||||
|
u16 *pDst = (u16*)(RDRAM + gDP.colorImage.address);
|
||||||
|
for (u32 x = 0; x < width; ++x)
|
||||||
|
pDst[(ulx + x) ^ 1] = swapword(pSrc[x]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool texturedRectCopyToItself(const GraphicsDrawer::TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
FrameBuffer * pCurrent = frameBufferList().getCurrent();
|
||||||
|
if (pCurrent != nullptr && pCurrent->m_size == G_IM_SIZ_8b && gSP.textureTile[0]->frameBuffer == pCurrent)
|
||||||
|
return true;
|
||||||
|
return texturedRectDepthBufferCopy(_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool texturedRectBGCopy(const GraphicsDrawer::TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
if (GBI.getMicrocodeType() != S2DEX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float flry = _params.lry;
|
||||||
|
if (flry > gDP.scissor.lry)
|
||||||
|
flry = gDP.scissor.lry;
|
||||||
|
|
||||||
|
const u32 width = (u32)(_params.lrx - _params.ulx);
|
||||||
|
const u32 tex_width = gSP.textureTile[0]->line << 3;
|
||||||
|
const u32 uly = (u32)_params.uly;
|
||||||
|
const u32 lry = flry;
|
||||||
|
|
||||||
|
u8 * texaddr = RDRAM + gDP.loadInfo[gSP.textureTile[0]->tmem].texAddress + tex_width*(u32)_params.ult + (u32)_params.uls;
|
||||||
|
u8 * fbaddr = RDRAM + gDP.colorImage.address + (u32)_params.ulx;
|
||||||
|
// LOG(LOG_VERBOSE, "memrect (%d, %d, %d, %d), ci_width: %d texaddr: 0x%08lx fbaddr: 0x%08lx\n", (u32)_params.ulx, uly, (u32)_params.lrx, lry, gDP.colorImage.width, gSP.textureTile[0]->imageAddress + tex_width*(u32)_params.ult + (u32)_params.uls, gDP.colorImage.address + (u32)_params.ulx);
|
||||||
|
|
||||||
|
for (u32 y = uly; y < lry; ++y) {
|
||||||
|
u8 *src = texaddr + (y - uly) * tex_width;
|
||||||
|
u8 *dst = fbaddr + y * gDP.colorImage.width;
|
||||||
|
memcpy(dst, src, width);
|
||||||
|
}
|
||||||
|
frameBufferList().removeBuffer(gDP.colorImage.address);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool texturedRectPaletteMod(const GraphicsDrawer::TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
if (gDP.textureImage.address == 0x400) {
|
||||||
|
// Paper Mario uses complex set of actions to prepare darkness texture.
|
||||||
|
// It includes manipulations with texture formats and drawing buffer into itsels.
|
||||||
|
// All that stuff is hardly possible to reproduce with GL, so I just use dirty hacks to emualte it.
|
||||||
|
|
||||||
|
if (gDP.colorImage.address == 0x400 && gDP.colorImage.width == 64) {
|
||||||
|
memcpy(RDRAM + 0x400, RDRAM + 0x14d500, 4096);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gDP.textureImage.width == 64) {
|
||||||
|
gDPTile & curTile = gDP.tiles[0];
|
||||||
|
curTile.frameBuffer = nullptr;
|
||||||
|
curTile.textureMode = TEXTUREMODE_NORMAL;
|
||||||
|
textureCache().update(0);
|
||||||
|
currentCombiner()->update(false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify palette for Paper Mario "2D lighting" effect
|
||||||
|
if (gDP.scissor.lrx != 16 || gDP.scissor.lry != 1 || _params.lrx != 16 || _params.lry != 1)
|
||||||
|
return false;
|
||||||
|
u8 envr = (u8)(gDP.envColor.r * 31.0f);
|
||||||
|
u8 envg = (u8)(gDP.envColor.g * 31.0f);
|
||||||
|
u8 envb = (u8)(gDP.envColor.b * 31.0f);
|
||||||
|
u16 env16 = (u16)((envr << 11) | (envg << 6) | (envb << 1) | 1);
|
||||||
|
u8 prmr = (u8)(gDP.primColor.r * 31.0f);
|
||||||
|
u8 prmg = (u8)(gDP.primColor.g * 31.0f);
|
||||||
|
u8 prmb = (u8)(gDP.primColor.b * 31.0f);
|
||||||
|
u16 prim16 = (u16)((prmr << 11) | (prmg << 6) | (prmb << 1) | 1);
|
||||||
|
u16 * src = (u16*)&TMEM[256];
|
||||||
|
u16 * dst = (u16*)(RDRAM + gDP.colorImage.address);
|
||||||
|
for (u32 i = 0; i < 16; ++i)
|
||||||
|
dst[i ^ 1] = (src[i << 2] & 0x100) ? prim16 : env16;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool texturedRectMonochromeBackground(const GraphicsDrawer::TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
if (gDP.textureImage.address >= gDP.colorImage.address && gDP.textureImage.address <= (gDP.colorImage.address + gDP.colorImage.width*gDP.colorImage.height * 2)) {
|
||||||
|
#ifdef GL_IMAGE_TEXTURES_SUPPORT
|
||||||
|
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
|
||||||
|
if (pCurrentBuffer != nullptr) {
|
||||||
|
FrameBuffer_ActivateBufferTexture(0, pCurrentBuffer);
|
||||||
|
CombinerInfo::get().setMonochromeCombiner();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special processing of textured rect.
|
||||||
|
// Return true if actuial rendering is not necessary
|
||||||
|
bool(*texturedRectSpecial)(const GraphicsDrawer::TexturedRectParams & _params) = nullptr;
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
gSP.changed &= ~CHANGED_GEOMETRYMODE; // Don't update cull mode
|
||||||
|
m_drawingState = DrawingState::TexRect;
|
||||||
|
f32 alpha = 0.0f;
|
||||||
|
|
||||||
|
if (!m_texrectDrawer.isEmpty()) {
|
||||||
|
CombinerInfo & cmbInfo = CombinerInfo::get();
|
||||||
|
cmbInfo.setPolygonMode(DrawingState::TexRect);
|
||||||
|
cmbInfo.update();
|
||||||
|
_updateTextures();
|
||||||
|
cmbInfo.updateParameters();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (_params.texrectCmd && (gSP.changed | gDP.changed) != 0)
|
||||||
|
_updateStates(DrawingState::TexRect);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
if (CombinerInfo::get().isChanged()) {
|
||||||
|
if (currentCombiner()->usesShade()) {
|
||||||
|
gDPCombine combine;
|
||||||
|
combine.mux = currentCombiner()->getKey().getMux();
|
||||||
|
if (combine.mA0 == G_ACMUX_0 && combine.aA0 == G_ACMUX_SHADE)
|
||||||
|
alpha = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_params.texrectCmd && texturedRectSpecial != nullptr && texturedRectSpecial(_params)) {
|
||||||
|
gSP.changed |= CHANGED_GEOMETRYMODE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_canDraw())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CombinerProgram * pCurrentCombiner = currentCombiner();
|
||||||
|
const FrameBuffer * pCurrentBuffer = _params.pBuffer;
|
||||||
|
OGLVideo & ogl = video();
|
||||||
|
TextureCache & cache = textureCache();
|
||||||
|
const bool bUseBilinear = (gDP.otherMode.textureFilter | (gSP.objRendermode&G_OBJRM_BILERP)) != 0;
|
||||||
|
const bool bUseTexrectDrawer = config.generalEmulation.enableNativeResTexrects != 0
|
||||||
|
&& bUseBilinear
|
||||||
|
&& pCurrentCombiner->usesTexture()
|
||||||
|
&& (pCurrentBuffer == nullptr || !pCurrentBuffer->m_cfb)
|
||||||
|
&& (cache.current[0] != nullptr)
|
||||||
|
// && (cache.current[0] == nullptr || cache.current[0]->format == G_IM_FMT_RGBA || cache.current[0]->format == G_IM_FMT_CI)
|
||||||
|
&& ((cache.current[0]->frameBufferTexture == CachedTexture::fbNone && !cache.current[0]->bHDTexture))
|
||||||
|
&& (cache.current[1] == nullptr || (cache.current[1]->frameBufferTexture == CachedTexture::fbNone && !cache.current[1]->bHDTexture));
|
||||||
|
|
||||||
|
const float scaleX = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_width : VI.rwidth;
|
||||||
|
const float scaleY = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_height : VI.rheight;
|
||||||
|
const float Z = (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : 0.0f;
|
||||||
|
const float W = 1.0f;
|
||||||
|
f32 uly, lry;
|
||||||
|
if (bUseTexrectDrawer) {
|
||||||
|
uly = (float)_params.uly * (2.0f * scaleY) - 1.0f;
|
||||||
|
lry = (float)_params.lry * (2.0f * scaleY) - 1.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uly = (float)_params.uly * (-2.0f * scaleY) + 1.0f;
|
||||||
|
lry = (float)(_params.lry) * (-2.0f * scaleY) + 1.0f;
|
||||||
|
// Flush text drawer
|
||||||
|
if (m_texrectDrawer.draw())
|
||||||
|
_updateStates(DrawingState::TexRect);
|
||||||
|
}
|
||||||
|
m_rect[0].x = (float)_params.ulx * (2.0f * scaleX) - 1.0f;
|
||||||
|
m_rect[0].y = uly;
|
||||||
|
m_rect[0].z = Z;
|
||||||
|
m_rect[0].w = W;
|
||||||
|
m_rect[1].x = (float)(_params.lrx) * (2.0f * scaleX) - 1.0f;
|
||||||
|
m_rect[1].y = m_rect[0].y;
|
||||||
|
m_rect[1].z = Z;
|
||||||
|
m_rect[1].w = W;
|
||||||
|
m_rect[2].x = m_rect[0].x;
|
||||||
|
m_rect[2].y = lry;
|
||||||
|
m_rect[2].z = Z;
|
||||||
|
m_rect[2].w = W;
|
||||||
|
m_rect[3].x = m_rect[1].x;
|
||||||
|
m_rect[3].y = m_rect[2].y;
|
||||||
|
m_rect[3].z = Z;
|
||||||
|
m_rect[3].w = W;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float s0, t0, s1, t1;
|
||||||
|
} texST[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; //struct for texture coordinates
|
||||||
|
|
||||||
|
for (u32 t = 0; t < 2; ++t) {
|
||||||
|
if (pCurrentCombiner->usesTile(t) && cache.current[t] && gSP.textureTile[t]) {
|
||||||
|
f32 shiftScaleS = 1.0f;
|
||||||
|
f32 shiftScaleT = 1.0f;
|
||||||
|
getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
|
||||||
|
if (_params.uls > _params.lrs) {
|
||||||
|
texST[t].s0 = (_params.uls + _params.dsdx) * shiftScaleS - gSP.textureTile[t]->fuls;
|
||||||
|
texST[t].s1 = _params.lrs * shiftScaleS - gSP.textureTile[t]->fuls;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
texST[t].s0 = _params.uls * shiftScaleS - gSP.textureTile[t]->fuls;
|
||||||
|
texST[t].s1 = (_params.lrs + _params.dsdx) * shiftScaleS - gSP.textureTile[t]->fuls;
|
||||||
|
}
|
||||||
|
if (_params.ult > _params.lrt) {
|
||||||
|
texST[t].t0 = (_params.ult + _params.dtdy) * shiftScaleT - gSP.textureTile[t]->fult;
|
||||||
|
texST[t].t1 = _params.lrt * shiftScaleT - gSP.textureTile[t]->fult;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
texST[t].t0 = _params.ult * shiftScaleT - gSP.textureTile[t]->fult;
|
||||||
|
texST[t].t1 = (_params.lrt + _params.dtdy) * shiftScaleT - gSP.textureTile[t]->fult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache.current[t]->frameBufferTexture != CachedTexture::fbNone) {
|
||||||
|
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
|
||||||
|
texST[t].t0 = cache.current[t]->offsetT - texST[t].t0;
|
||||||
|
texST[t].s1 = cache.current[t]->offsetS + texST[t].s1;
|
||||||
|
texST[t].t1 = cache.current[t]->offsetT - texST[t].t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context::TexParameters texParams;
|
||||||
|
|
||||||
|
if ((cache.current[t]->mirrorS == 0 && cache.current[t]->maskS == 0 &&
|
||||||
|
(texST[t].s0 < texST[t].s1 ?
|
||||||
|
texST[t].s0 >= 0.0 && texST[t].s1 <= (float)cache.current[t]->width :
|
||||||
|
texST[t].s1 >= 0.0 && texST[t].s0 <= (float)cache.current[t]->width))
|
||||||
|
|| (cache.current[t]->maskS == 0 && (texST[t].s0 < -1024.0f || texST[t].s1 > 1023.99f)))
|
||||||
|
texParams.wrapS = textureParameters::WRAP_CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
if (cache.current[t]->mirrorT == 0 &&
|
||||||
|
(texST[t].t0 < texST[t].t1 ?
|
||||||
|
texST[t].t0 >= 0.0f && texST[t].t1 <= (float)cache.current[t]->height :
|
||||||
|
texST[t].t1 >= 0.0f && texST[t].t0 <= (float)cache.current[t]->height))
|
||||||
|
texParams.wrapT = textureParameters::WRAP_CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
if (texParams.wrapS.isValid() || texParams.wrapT.isValid()) {
|
||||||
|
texParams.handle = ObjectHandle(cache.current[t]->glName);
|
||||||
|
texParams.textureUnitIndex = textureIndices::Tex[t];
|
||||||
|
gfxContext.setTextureParameters(texParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
texST[t].s0 *= cache.current[t]->scaleS;
|
||||||
|
texST[t].t0 *= cache.current[t]->scaleT;
|
||||||
|
texST[t].s1 *= cache.current[t]->scaleS;
|
||||||
|
texST[t].t1 *= cache.current[t]->scaleT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gDP.otherMode.cycleType == G_CYC_COPY) {
|
||||||
|
Context::TexParameters texParams;
|
||||||
|
texParams.handle = ObjectHandle(cache.current[0]->glName);
|
||||||
|
texParams.textureUnitIndex = textureIndices::Tex[0];
|
||||||
|
texParams.minFilter = textureParameters::FILTER_NEAREST;
|
||||||
|
texParams.magFilter = textureParameters::FILTER_NEAREST;
|
||||||
|
gfxContext.setTextureParameters(texParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rect[0].s0 = texST[0].s0;
|
||||||
|
m_rect[0].t0 = texST[0].t0;
|
||||||
|
m_rect[0].s1 = texST[1].s0;
|
||||||
|
m_rect[0].t1 = texST[1].t0;
|
||||||
|
|
||||||
|
m_rect[3].s0 = texST[0].s1;
|
||||||
|
m_rect[3].t0 = texST[0].t1;
|
||||||
|
m_rect[3].s1 = texST[1].s1;
|
||||||
|
m_rect[3].t1 = texST[1].t1;
|
||||||
|
|
||||||
|
if (_params.flip) {
|
||||||
|
m_rect[1].s0 = texST[0].s0;
|
||||||
|
m_rect[1].t0 = texST[0].t1;
|
||||||
|
m_rect[1].s1 = texST[1].s0;
|
||||||
|
m_rect[1].t1 = texST[1].t1;
|
||||||
|
|
||||||
|
m_rect[2].s0 = texST[0].s1;
|
||||||
|
m_rect[2].t0 = texST[0].t0;
|
||||||
|
m_rect[2].s1 = texST[1].s1;
|
||||||
|
m_rect[2].t1 = texST[1].t0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_rect[1].s0 = texST[0].s1;
|
||||||
|
m_rect[1].t0 = texST[0].t0;
|
||||||
|
m_rect[1].s1 = texST[1].s1;
|
||||||
|
m_rect[1].t1 = texST[1].t0;
|
||||||
|
|
||||||
|
m_rect[2].s0 = texST[0].s0;
|
||||||
|
m_rect[2].t0 = texST[0].t1;
|
||||||
|
m_rect[2].s1 = texST[1].s0;
|
||||||
|
m_rect[2].t1 = texST[1].t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ogl.isAdjustScreen() &&
|
||||||
|
(_params.forceAjustScale ||
|
||||||
|
((gDP.colorImage.width > VI.width * 98 / 100) && (_params.lrx - _params.ulx < VI.width * 9 / 10))))
|
||||||
|
{
|
||||||
|
const float scale = ogl.getAdjustScale();
|
||||||
|
for (u32 i = 0; i < 4; ++i)
|
||||||
|
m_rect[i].x *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUseTexrectDrawer)
|
||||||
|
m_texrectDrawer.add();
|
||||||
|
else {
|
||||||
|
if (pCurrentBuffer == nullptr)
|
||||||
|
gfxContext.setViewport(0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight());
|
||||||
|
else
|
||||||
|
gfxContext.setViewport(0, 0, pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX, pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY);
|
||||||
|
|
||||||
|
graphics::DrawerImpl::DrawRectParameters rectParams;
|
||||||
|
rectParams.mode = drawmode::TRIANGLE_STRIP;
|
||||||
|
rectParams.rectColor.fill(0.0f);
|
||||||
|
rectParams.rectColor[3] = alpha;
|
||||||
|
rectParams.verticesCount = 4;
|
||||||
|
rectParams.vertices = m_rect;
|
||||||
|
rectParams.combiner = currentCombiner();
|
||||||
|
m_drawerImpl->drawRects(rectParams);
|
||||||
|
|
||||||
|
gSP.changed |= CHANGED_GEOMETRYMODE | CHANGED_VIEWPORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::correctTexturedRectParams(TexturedRectParams & _params)
|
||||||
|
{
|
||||||
|
if (config.generalEmulation.correctTexrectCoords == Config::tcSmart) {
|
||||||
|
if (_params.ulx == m_texrectParams.ulx && _params.lrx == m_texrectParams.lrx) {
|
||||||
|
if (fabsf(_params.uly - m_texrectParams.lry) < 0.51f)
|
||||||
|
_params.uly = m_texrectParams.lry;
|
||||||
|
else if (fabsf(_params.lry - m_texrectParams.uly) < 0.51f)
|
||||||
|
_params.lry = m_texrectParams.uly;
|
||||||
|
}
|
||||||
|
else if (_params.uly == m_texrectParams.uly && _params.lry == m_texrectParams.lry) {
|
||||||
|
if (fabsf(_params.ulx - m_texrectParams.lrx) < 0.51f)
|
||||||
|
_params.ulx = m_texrectParams.lrx;
|
||||||
|
else if (fabsf(_params.lrx - m_texrectParams.ulx) < 0.51f)
|
||||||
|
_params.lrx = m_texrectParams.ulx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (config.generalEmulation.correctTexrectCoords == Config::tcForce) {
|
||||||
|
_params.lrx += 0.25f;
|
||||||
|
_params.lry += 0.25f;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_texrectParams = _params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawText(const char *_pText, float x, float y)
|
||||||
|
{
|
||||||
|
m_drawingState = DrawingState::None;
|
||||||
|
m_textDrawer->renderText(_pText, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::_getTextSize(const char *_pText, float & _w, float & _h) const
|
||||||
|
{
|
||||||
|
m_textDrawer->getTextSize(_pText, _w, _h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::_drawOSD(const char *_pText, float _x, float & _y)
|
||||||
|
{
|
||||||
|
float tW, tH;
|
||||||
|
_getTextSize(_pText, tW, tH);
|
||||||
|
|
||||||
|
const bool top = (config.posTop & config.onScreenDisplay.pos) != 0;
|
||||||
|
const bool right = (config.onScreenDisplay.pos == Config::posTopRight) || (config.onScreenDisplay.pos == Config::posBottomRight);
|
||||||
|
const bool center = (config.onScreenDisplay.pos == Config::posTopCenter) || (config.onScreenDisplay.pos == Config::posBottomCenter);
|
||||||
|
|
||||||
|
if (center)
|
||||||
|
_x = -tW * 0.5f;
|
||||||
|
else if (right)
|
||||||
|
_x -= tW;
|
||||||
|
|
||||||
|
if (top)
|
||||||
|
_y -= tH;
|
||||||
|
|
||||||
|
drawText(_pText, _x, _y);
|
||||||
|
|
||||||
|
if (top)
|
||||||
|
_y -= tH * 0.5f;
|
||||||
|
else
|
||||||
|
_y += tH * 1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::drawOSD()
|
||||||
|
{
|
||||||
|
if ((config.onScreenDisplay.fps | config.onScreenDisplay.vis | config.onScreenDisplay.percent) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
DisplayWindow & wnd = DisplayWindow::get();
|
||||||
|
const GLint X = (wnd.getScreenWidth() - wnd.getWidth()) / 2;
|
||||||
|
const GLint Y = wnd.getHeightOffset();
|
||||||
|
const GLint W = wnd.getWidth();
|
||||||
|
const GLint H = wnd.getHeight();
|
||||||
|
glViewport(X, Y, W, H);
|
||||||
|
glScissor(X, Y, W, H);
|
||||||
|
gSP.changed |= CHANGED_VIEWPORT;
|
||||||
|
gDP.changed |= CHANGED_SCISSOR;
|
||||||
|
|
||||||
|
|
||||||
|
const bool bottom = (config.posBottom & config.onScreenDisplay.pos) != 0;
|
||||||
|
const bool left = (config.onScreenDisplay.pos == Config::posTopLeft) || (config.onScreenDisplay.pos == Config::posBottomLeft);
|
||||||
|
|
||||||
|
const float hp = left ? -1 : 1;
|
||||||
|
const float vp = bottom ? -1 : 1;
|
||||||
|
|
||||||
|
float hShift, vShift;
|
||||||
|
_getTextSize("0", hShift, vShift);
|
||||||
|
hShift *= 0.5f;
|
||||||
|
vShift *= 0.5f;
|
||||||
|
const float x = hp - hShift * hp;
|
||||||
|
float y = vp - vShift * vp;
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
if (config.onScreenDisplay.fps) {
|
||||||
|
sprintf(buf, "%d FPS", int(perf.getFps()));
|
||||||
|
_drawOSD(buf, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.onScreenDisplay.vis) {
|
||||||
|
sprintf(buf, "%d VI/S", int(perf.getVIs()));
|
||||||
|
_drawOSD(buf, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.onScreenDisplay.percent) {
|
||||||
|
sprintf(buf, "%d %%", int(perf.getPercent()));
|
||||||
|
_drawOSD(buf, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
frameBufferList().setCurrentDrawBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::clearDepthBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry)
|
||||||
|
{
|
||||||
|
if (!_canDraw())
|
||||||
|
return;
|
||||||
|
|
||||||
|
depthBufferList().clearBuffer(_ulx, _uly, _lrx, _lry);
|
||||||
|
|
||||||
|
gfxContext.clearDepthBuffer();
|
||||||
|
|
||||||
|
_updateDepthUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDrawer::clearColorBuffer(float *_pColor)
|
||||||
|
{
|
||||||
|
if (_pColor != nullptr)
|
||||||
|
gfxContext.clearColorBuffer(_pColor[0], _pColor[1], _pColor[2], _pColor[3]);
|
||||||
|
else
|
||||||
|
gfxContext.clearColorBuffer(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
class DrawerImpl;
|
class DrawerImpl;
|
||||||
|
class TextDrawer;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CachedTexture;
|
struct CachedTexture;
|
||||||
|
@ -134,7 +135,7 @@ private:
|
||||||
void _updateDepthCompare() const;
|
void _updateDepthCompare() const;
|
||||||
void _updateTextures() const;
|
void _updateTextures() const;
|
||||||
void _updateStates(DrawingState _drawingState) const;
|
void _updateStates(DrawingState _drawingState) const;
|
||||||
void _prepareDrawTriangle(bool _dma);
|
void _prepareDrawTriangle();
|
||||||
bool _canDraw() const;
|
bool _canDraw() const;
|
||||||
void _drawThickLine(int _v0, int _v1, float _width);
|
void _drawThickLine(int _v0, int _v1, float _width);
|
||||||
|
|
||||||
|
@ -144,6 +145,18 @@ private:
|
||||||
DrawingState m_drawingState;
|
DrawingState m_drawingState;
|
||||||
TexturedRectParams m_texrectParams;
|
TexturedRectParams m_texrectParams;
|
||||||
|
|
||||||
|
// Dummy TexrectDrawer
|
||||||
|
class TexrectDrawer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TexrectDrawer() {}
|
||||||
|
void init() {}
|
||||||
|
void destroy() {}
|
||||||
|
void add() {}
|
||||||
|
bool draw() { return false; }
|
||||||
|
bool isEmpty() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::array<SPVertex, VERTBUFF_SIZE> vertices;
|
std::array<SPVertex, VERTBUFF_SIZE> vertices;
|
||||||
std::array<u8, ELEMBUFF_SIZE> elements;
|
std::array<u8, ELEMBUFF_SIZE> elements;
|
||||||
|
@ -159,9 +172,10 @@ private:
|
||||||
f32 m_maxLineWidth;
|
f32 m_maxLineWidth;
|
||||||
bool m_bImageTexture;
|
bool m_bImageTexture;
|
||||||
bool m_bFlatColors;
|
bool m_bFlatColors;
|
||||||
bool m_bDmaVertices;
|
TexrectDrawer m_texrectDrawer;
|
||||||
|
|
||||||
std::unique_ptr<graphics::DrawerImpl> m_drawerImpl;
|
std::unique_ptr<graphics::DrawerImpl> m_drawerImpl;
|
||||||
|
std::unique_ptr<graphics::TextDrawer> m_textDrawer;
|
||||||
|
|
||||||
//GLuint m_programCopyTex;
|
//GLuint m_programCopyTex;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user