1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-26 02:14:22 +00:00

OpenGL improvements.

This commit is contained in:
jules 2011-12-13 22:10:33 +00:00
parent d6ed09e158
commit f703feb61e
2 changed files with 320 additions and 104 deletions

View file

@ -389,6 +389,7 @@ bool OpenGLFrameBuffer::readPixels (PixelARGB* target, const Rectangle<int>& are
glPixelStorei (GL_PACK_ALIGNMENT, 4);
glReadPixels (area.getX(), area.getY(), area.getWidth(), area.getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, target);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glPixelStorei (GL_PACK_ALIGNMENT, 0);
return true;
}

View file

@ -25,6 +25,10 @@
BEGIN_JUCE_NAMESPACE
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX
// #define JUCE_USE_OPENGL_SHADERS 1
#endif
namespace
{
#if JUCE_WINDOWS
@ -45,23 +49,65 @@ namespace
GL_COMBINE_RGB = 0x8571,
GL_COMBINE_ALPHA = 0x8572,
GL_PREVIOUS = 0x8578,
GL_COMPILE_STATUS = 0x8B81,
GL_LINK_STATUS = 0x8B82,
GL_SHADING_LANGUAGE_VERSION = 0x8B8C,
GL_FRAGMENT_SHADER = 0x8B30
};
typedef char GLchar;
#endif
#if JUCE_WINDOWS || JUCE_LINUX
JUCE_DECLARE_GL_EXTENSION_FUNCTION (glActiveTexture, void, (GLenum));
JUCE_DECLARE_GL_EXTENSION_FUNCTION (glClientActiveTexture, void, (GLenum));
void initialiseMultiTextureExtensions()
{
if (glActiveTexture == nullptr)
{
JUCE_INSTANTIATE_GL_EXTENSION (glActiveTexture);
JUCE_INSTANTIATE_GL_EXTENSION (glClientActiveTexture);
}
}
#if JUCE_USE_OPENGL_SHADERS
#define WINDOWS_GL_FUNCTION_LIST(USE_FUNCTION) \
USE_FUNCTION (glActiveTexture, void, (GLenum))\
USE_FUNCTION (glClientActiveTexture, void, (GLenum))\
USE_FUNCTION (glCreateProgram, GLuint, ())\
USE_FUNCTION (glDeleteProgram, void, (GLuint))\
USE_FUNCTION (glCreateShader, GLuint, (GLenum))\
USE_FUNCTION (glDeleteShader, void, (GLuint))\
USE_FUNCTION (glShaderSource, void, (GLuint, GLsizei, const GLchar**, const GLint*))\
USE_FUNCTION (glCompileShader, void, (GLuint))\
USE_FUNCTION (glAttachShader, void, (GLuint, GLuint))\
USE_FUNCTION (glLinkProgram, void, (GLuint))\
USE_FUNCTION (glUseProgram, void, (GLuint))\
USE_FUNCTION (glGetShaderiv, void, (GLuint, GLenum, GLint*))\
USE_FUNCTION (glGetShaderInfoLog, void, (GLuint, GLsizei, GLsizei*, GLchar*))\
USE_FUNCTION (glGetProgramiv, void, (GLuint, GLenum, GLint*))\
USE_FUNCTION (glGetUniformLocation, GLint, (GLuint, const GLchar*))\
USE_FUNCTION (glUniform1f, void, (GLint, GLfloat))\
USE_FUNCTION (glUniform1i, void, (GLint, GLint))\
USE_FUNCTION (glUniform2f, void, (GLint, GLfloat, GLfloat))\
USE_FUNCTION (glUniform3f, void, (GLint, GLfloat, GLfloat, GLfloat))\
USE_FUNCTION (glUniform4f, void, (GLint, GLfloat, GLfloat, GLfloat, GLfloat))\
USE_FUNCTION (glUniform4i, void, (GLint, GLint, GLint, GLint, GLint))\
USE_FUNCTION (glUniformMatrix2x3fv, void, (GLint, GLsizei, GLboolean, const GLfloat*))\
#else
void initialiseMultiTextureExtensions() {}
#define WINDOWS_GL_FUNCTION_LIST(USE_FUNCTION) \
USE_FUNCTION (glActiveTexture, void, (GLenum))\
USE_FUNCTION (glClientActiveTexture, void, (GLenum))
#endif
WINDOWS_GL_FUNCTION_LIST (JUCE_DECLARE_GL_EXTENSION_FUNCTION)
static bool windowsFunctionsInitialised = false;
void initialiseWindowsExtensions()
{
windowsFunctionsInitialised = true;
#define FIND_FUNCTION(name, returnType, params) name = (type_ ## name) OpenGLHelpers::getExtensionFunction (#name);
WINDOWS_GL_FUNCTION_LIST (FIND_FUNCTION)
#undef FIND_FUNCTION
}
#undef WINDOWS_GL_FUNCTION_LIST
#else
void initialiseWindowsExtensions() {}
#endif
}
@ -242,15 +288,15 @@ namespace
//==============================================================================
#if JUCE_USE_OPENGL_SHADERS
class GLShaderProgram
class OpenGLShaderProgram
{
public:
GLShaderProgram() noexcept
OpenGLShaderProgram() noexcept
: program (glCreateProgram())
{
}
~GLShaderProgram() noexcept
~OpenGLShaderProgram() noexcept
{
glDeleteProgram (program);
}
@ -292,7 +338,7 @@ public:
struct Uniform
{
Uniform (const GLShaderProgram& program, const GLchar* name)
Uniform (const OpenGLShaderProgram& program, const GLchar* name)
: uniformID (glGetUniformLocation (program.program, name))
{
jassert (uniformID >= 0);
@ -315,6 +361,9 @@ public:
};
GLuint program;
private:
JUCE_DECLARE_NON_COPYABLE (OpenGLShaderProgram);
};
struct ShaderPrograms
@ -332,11 +381,48 @@ struct ShaderPrograms
{
ShaderBase (const char* fragmentShader)
{
addShader (fragmentShader, GL_FRAGMENT_SHADER);
link();
program.addShader (fragmentShader, GL_FRAGMENT_SHADER);
program.link();
}
GLShaderProgram program;
OpenGLShaderProgram program;
};
struct MaskedShaderParams
{
MaskedShaderParams (const OpenGLShaderProgram& program)
: maskTexture (program, "maskTexture"),
maskBounds (program, "maskBounds")
{}
OpenGLShaderProgram::Uniform maskTexture, maskBounds;
};
struct RadialGradientParams
{
RadialGradientParams (const OpenGLShaderProgram& program)
: gradientTexture (program, "gradientTexture"),
matrix (program, "matrix")
{}
void setMatrix (const Point<float>& p1, const Point<float>& p2, const Point<float>& p3)
{
matrix.set (AffineTransform::fromTargetPoints (p1.x, p1.y, 0.0f, 0.0f,
p2.x, p2.y, 1.0f, 0.0f,
p3.x, p3.y, 0.0f, 1.0f));
}
OpenGLShaderProgram::Uniform gradientTexture, matrix;
};
struct LinearGradientParams
{
LinearGradientParams (const OpenGLShaderProgram& program)
: gradientTexture (program, "gradientTexture"),
gradientInfo (program, "gradientInfo")
{}
OpenGLShaderProgram::Uniform gradientTexture, gradientInfo;
};
struct SolidColourMaskedProgram : public ShaderBase
@ -345,21 +431,19 @@ struct ShaderPrograms
: ShaderBase ("#version 120\n"
"uniform sampler2D maskTexture;"
"uniform ivec4 maskBounds;"
"const float textureY = 0.5;"
""
"void main()"
"{"
" vec2 maskPos;"
" maskPos.x = (gl_FragCoord.x - maskBounds.x) / maskBounds.z;"
" maskPos.y = 1.0 - (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" gl_FragColor = gl_Color * texture2D (maskTexture, maskPos).w;"
" maskPos.y = (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" gl_FragColor = gl_Color * texture2D (maskTexture, maskPos).a;"
"}"),
maskTexture (program, "maskTexture"),
maskBounds (program, "maskBounds")
maskParams (program)
{
}
GLShaderProgram::Uniform maskTexture, maskBounds;
MaskedShaderParams maskParams;
};
struct RadialGradientProgram : public ShaderBase
@ -376,12 +460,11 @@ struct ShaderPrograms
" matrix[1][0] * gl_FragCoord.x + matrix[1][1] * gl_FragCoord.y + matrix[1][2]));"
" gl_FragColor = gl_Color.w * texture2D (gradientTexture, vec2 (dist, textureY));"
"}"),
gradientTexture (program, "gradientTexture"),
matrix (program, "matrix")
gradientParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, matrix;
RadialGradientParams gradientParams;
};
struct RadialGradientMaskedProgram : public ShaderBase
@ -402,20 +485,18 @@ struct ShaderPrograms
""
" vec2 maskPos;"
" maskPos.x = (gl_FragCoord.x - maskBounds.x) / maskBounds.z;"
" maskPos.y = 1.0 - (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).w;"
" maskPos.y = (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).a;"
""
" gl_FragColor = result;"
"}"),
gradientTexture (program, "gradientTexture"),
matrix (program, "matrix"),
maskTexture (program, "maskTexture"),
maskBounds (program, "maskBounds")
gradientParams (program),
maskParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, matrix;
GLShaderProgram::Uniform maskTexture, maskBounds;
RadialGradientParams gradientParams;
MaskedShaderParams maskParams;
};
struct LinearGradient1Program : public ShaderBase
@ -431,12 +512,11 @@ struct ShaderPrograms
" float dist = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.z * (gl_FragCoord.x - gradientInfo.x)))) / gradientInfo.w;"
" gl_FragColor = gl_Color.w * texture2D (gradientTexture, vec2 (dist, textureY));"
"}"),
gradientTexture (program, "gradientTexture"),
gradientInfo (program, "gradientInfo")
gradientParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, gradientInfo;
LinearGradientParams gradientParams;
};
struct LinearGradient1MaskedProgram : public ShaderBase
@ -444,31 +524,29 @@ struct ShaderPrograms
LinearGradient1MaskedProgram()
: ShaderBase ("#version 120\n"
"uniform sampler2D gradientTexture;"
"uniform vec3 gradientInfo;" // x = (x2 - x1) / (y2 - y1), y = x1, z = length
"uniform vec4 gradientInfo;" // x = x1, y = y1, z = (y2 - y1) / (x2 - x1), w = length
"uniform sampler2D maskTexture;"
"uniform ivec4 maskBounds;"
"const float textureY = 0.5;"
""
"void main()"
"{"
" float dist = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.x * (gl_FragCoord.x - gradientInfo.y)))) / gradientInfo.z;"
" float dist = (gl_FragCoord.y - (gradientInfo.y + (gradientInfo.z * (gl_FragCoord.x - gradientInfo.x)))) / gradientInfo.w;"
" vec4 result = gl_Color.w * texture2D (gradientTexture, vec2 (dist, textureY));"
""
" vec2 maskPos;"
" maskPos.x = (gl_FragCoord.x - maskBounds.x) / maskBounds.z;"
" maskPos.y = 1.0 - (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).w;"
" maskPos.y = (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).a;"
" gl_FragColor = result;"
"}"),
gradientTexture (program, "gradientTexture"),
gradientInfo (program, "gradientInfo"),
maskTexture (program, "maskTexture"),
maskBounds (program, "maskBounds")
gradientParams (program),
maskParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, gradientInfo;
GLShaderProgram::Uniform maskTexture, maskBounds;
LinearGradientParams gradientParams;
MaskedShaderParams maskParams;
};
struct LinearGradient2Program : public ShaderBase
@ -484,12 +562,11 @@ struct ShaderPrograms
" float dist = (gl_FragCoord.x - (gradientInfo.x + (gradientInfo.z * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.w;"
" gl_FragColor = gl_Color.w * texture2D (gradientTexture, vec2 (dist, textureY));"
"}"),
gradientTexture (program, "gradientTexture"),
gradientInfo (program, "gradientInfo")
gradientParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, gradientInfo;
LinearGradientParams gradientParams;
};
struct LinearGradient2MaskedProgram : public ShaderBase
@ -497,31 +574,29 @@ struct ShaderPrograms
LinearGradient2MaskedProgram()
: ShaderBase ("#version 120\n"
"uniform sampler2D gradientTexture;"
"uniform vec3 gradientInfo;" // x = (y2 - y1) / (x2 - x1), y = y1, z = length
"uniform vec4 gradientInfo;" // x = x1, y = y1, z = (x2 - x1) / (y2 - y1), y = y1, w = length
"uniform sampler2D maskTexture;"
"uniform ivec4 maskBounds;"
"const float textureY = 0.5;"
""
"void main()"
"{"
" float dist = (gl_FragCoord.x - (gradientInfo.y + (gradientInfo.x * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.z;"
" float dist = (gl_FragCoord.x - (gradientInfo.x + (gradientInfo.z * (gl_FragCoord.y - gradientInfo.y)))) / gradientInfo.w;"
" vec4 result = gl_Color.w * texture2D (gradientTexture, vec2 (dist, textureY));"
""
" vec2 maskPos;"
" maskPos.x = (gl_FragCoord.x - maskBounds.x) / maskBounds.z;"
" maskPos.y = 1.0 - (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).w;"
" maskPos.y = (gl_FragCoord.y - maskBounds.y) / maskBounds.w;"
" result *= texture2D (maskTexture, maskPos).a;"
" gl_FragColor = result;"
"}"),
gradientTexture (program, "gradientTexture"),
gradientInfo (program, "gradientInfo"),
maskTexture (program, "maskTexture"),
maskBounds (program, "maskBounds")
gradientParams (program),
maskParams (program)
{
}
GLShaderProgram::Uniform gradientTexture, gradientInfo;
GLShaderProgram::Uniform maskTexture, maskBounds;
LinearGradientParams gradientParams;
MaskedShaderParams maskParams;
};
SolidColourMaskedProgram solidColourMasked;
@ -533,7 +608,7 @@ struct ShaderPrograms
LinearGradient2MaskedProgram linearGradient2Masked;
};
//static ScopedPointer<ShaderPrograms> programs;
static ScopedPointer<ShaderPrograms> programs;
#endif
class OpenGLRenderer::GLState
@ -549,7 +624,7 @@ public:
srcFunction (0), dstFunction (0),
currentColour (0),
quadQueueActive (false),
numVertices (0),
numIndices (0), numVertices (0),
activeGradientIndex (0),
gradientNeedsRefresh (true)
#if JUCE_USE_OPENGL_SHADERS
@ -559,7 +634,7 @@ public:
// This object can only be created and used when the current thread has an active OpenGL context.
jassert (OpenGLHelpers::isContextActive());
initialiseMultiTextureExtensions();
initialiseWindowsExtensions();
target.makeActiveFor2D();
glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_NORMAL_ARRAY);
@ -722,9 +797,11 @@ public:
}
else
{
#if JUCE_DEBUG
GLint t = 0;
glGetIntegerv (GL_TEXTURE_BINDING_2D, &t);
jassert (t == (GLint) textureID);
#endif
}
}
@ -768,7 +845,10 @@ public:
if ((textureIndexMask & (1 << i)) != 0)
glEnable (GL_TEXTURE_2D);
else
{
glDisable (GL_TEXTURE_2D);
currentTextureID[i] = 0;
}
}
}
@ -820,7 +900,7 @@ public:
{
if (! quadQueueActive)
{
jassert (numVertices == 0);
jassert (numIndices == 0 && numVertices == 0);
setTexturesEnabled (0);
glEnableClientState (GL_COLOR_ARRAY);
glVertexPointer (2, GL_SHORT, 0, vertices);
@ -840,22 +920,31 @@ public:
const GLshort y2 = (GLshort) (y + h);
GLshort* const v = vertices + numVertices * 2;
v[0] = x1; v[1] = y1; v[2] = x2; v[3] = y1; v[4] = x1; v[5] = y2;
v[6] = x2; v[7] = y1; v[8] = x1; v[9] = y2; v[10] = x2; v[11] = y2;
const uint32 rgba = colour.getInRGBAMemoryOrder();
v[0] = x1; v[1] = y1; v[2] = x2; v[3] = y1;
v[4] = x1; v[5] = y2; v[6] = x2; v[7] = y2;
uint32* const c = colours + numVertices;
for (int i = 0; i < 6; ++i)
c[i] = rgba;
c[0] = c[1] = c[2] = c[3] = colour.getInRGBAMemoryOrder();
numVertices += 6;
GLubyte* const i = indices + numIndices;
i[0] = (GLubyte) numVertices;
i[1] = i[3] = (GLubyte) (numVertices + 1);
i[2] = i[4] = (GLubyte) (numVertices + 2);
i[5] = (GLubyte) (numVertices + 3);
if (numVertices > maxVerticesPerBlock - 6)
{
glDrawArrays (GL_TRIANGLES, 0, numVertices);
numVertices = 0;
}
numVertices += 4;
numIndices += 6;
if (numIndices > maxVerticesPerBlock - 6)
drawQuadQueue();
}
void fillRect (const Rectangle<int>& r, const PixelARGB& colour) noexcept
{
jassert (! r.isEmpty());
checkQuadQueueActive();
addQuadToList (r.getX(), r.getY(), r.getWidth(), r.getHeight(), colour);
}
void fillRect (const Rectangle<float>& r, const PixelARGB& colour) noexcept
@ -1082,45 +1171,104 @@ public:
}
#if JUCE_USE_OPENGL_SHADERS
void setShaderForGradientFill (const FillType& fill)
void setShaderForGradientFill (const FillType& fill, PositionedTexture* mask)
{
setPremultipliedBlendingMode();
setSingleTextureMode();
setSolidColour();
const ColourGradient& g = *fill.gradient;
bindTextureForGradient (g);
const AffineTransform t (fill.transform.followedBy (AffineTransform::verticalFlip (target.height)));
if (mask != nullptr)
{
setTexturesEnabled (3);
setActiveTexture (1);
bindTexture (mask->textureID);
setActiveTexture (0);
bindTextureForGradient (g);
}
else
{
setSingleTextureMode();
bindTextureForGradient (g);
}
const AffineTransform t (fill.transform.translated ((float) -target.x, (float) -target.y)
.followedBy (AffineTransform::verticalFlip ((float) target.height)));
Point<float> p1 (g.point1.transformedBy (t));
const Point<float> p2 (g.point2.transformedBy (t));
const Point<float> p3 (Point<float> (g.point1.x + (g.point2.y - g.point1.y),
g.point1.y - (g.point2.x - g.point1.x)).transformedBy (t));
const ShaderPrograms::MaskedShaderParams* maskParams = nullptr;
if (g.isRadial)
{
setShader (&(programs->radialGradient.program));
programs->radialGradient.matrix.set (AffineTransform::fromTargetPoints (p1.x, p1.y, 0.0f, 0.0f,
p2.x, p2.y, 1.0f, 0.0f,
p3.x, p3.y, 0.0f, 1.0f));
ShaderPrograms::RadialGradientParams* gradientParams;
if (mask == nullptr)
{
setShader (programs->radialGradient);
gradientParams = &programs->radialGradient.gradientParams;
}
else
{
setShader (programs->radialGradientMasked);
gradientParams = &programs->radialGradientMasked.gradientParams;
maskParams = &programs->radialGradientMasked.maskParams;
}
gradientParams->setMatrix (p1, p2, p3);
}
else
{
p1 = Line<float> (p1, p3).findNearestPointTo (p2);
const Point<float> delta (p2.x - p1.x, p1.y - p2.y);
const ShaderPrograms::LinearGradientParams* gradientParams;
float grad, length;
if (std::abs (delta.x) < std::abs (delta.y))
{
setShader (&(programs->linearGradient1.program));
const float grad = delta.x / delta.y;
programs->linearGradient1.gradientInfo.set (p1.x, p1.y, grad, (p2.y - grad * p2.x) - (p1.y - grad * p1.x));
if (mask == nullptr)
{
setShader (programs->linearGradient1);
gradientParams = &(programs->linearGradient1.gradientParams);
}
else
{
setShader (programs->linearGradient1Masked);
gradientParams = &(programs->linearGradient1Masked.gradientParams);
maskParams = &programs->linearGradient1Masked.maskParams;
}
grad = delta.x / delta.y;
length = (p2.y - grad * p2.x) - (p1.y - grad * p1.x);
}
else
{
setShader (&(programs->linearGradient2.program));
const float grad = delta.y / delta.x;
programs->linearGradient2.gradientInfo.set (p1.x, p1.y, grad, (p2.x - grad * p2.y) - (p1.x - grad * p1.y));
if (mask == nullptr)
{
setShader (programs->linearGradient2);
gradientParams = &(programs->linearGradient2.gradientParams);
}
else
{
setShader (programs->linearGradient2Masked);
gradientParams = &(programs->linearGradient2Masked.gradientParams);
maskParams = &programs->linearGradient2Masked.maskParams;
}
grad = delta.y / delta.x;
length = (p2.x - grad * p2.y) - (p1.x - grad * p1.y);
}
gradientParams->gradientInfo.set (p1.x, p1.y, grad, length);
}
if (maskParams != nullptr)
{
maskParams->maskTexture.set ((GLint) 1);
maskParams->maskBounds.set (mask->area.getX() - target.x, target.height - (mask->area.getBottom() - target.y),
mask->area.getWidth(), mask->area.getHeight());
}
}
#endif
@ -1129,11 +1277,8 @@ public:
{
if (quadQueueActive)
{
if (numVertices > 0)
{
glDrawArrays (GL_TRIANGLES, 0, numVertices);
numVertices = 0;
}
if (numIndices > 0)
drawQuadQueue();
quadQueueActive = false;
glDisableClientState (GL_COLOR_ARRAY);
@ -1147,7 +1292,12 @@ public:
}
#if JUCE_USE_OPENGL_SHADERS
void setShader (GLShaderProgram* newShader)
void setShader (ShaderPrograms::ShaderBase& shader)
{
setShader (&(shader.program));
}
void setShader (OpenGLShaderProgram* newShader)
{
if (activeShader != newShader)
{
@ -1163,7 +1313,7 @@ public:
private:
enum
{
maxVerticesPerBlock = 192,
maxVerticesPerBlock = 192, // must not go over 256 because indices are 8-bit.
gradientTextureSize = 256,
numTexturesToCache = 8,
numGradientTexturesToCache = 6
@ -1178,18 +1328,26 @@ private:
bool quadQueueActive;
GLshort vertices [maxVerticesPerBlock * 2];
GLubyte indices [maxVerticesPerBlock];
uint32 colours [maxVerticesPerBlock];
int numVertices;
int numIndices, numVertices;
OwnedArray<OpenGLTexture> textures, gradientTextures;
int activeGradientIndex;
bool gradientNeedsRefresh;
#if JUCE_USE_OPENGL_SHADERS
GLShaderProgram* activeShader;
OpenGLShaderProgram* activeShader;
bool canUseShaders;
#endif
void drawQuadQueue()
{
glDrawElements (GL_TRIANGLES, numIndices, GL_UNSIGNED_BYTE, indices);
numIndices = 0;
numVertices = 0;
}
void resetMultiTextureMode (int index, const bool forRGBTextures)
{
setActiveTexture (index);
@ -1609,6 +1767,27 @@ public:
if (! r.isEmpty())
{
#if JUCE_USE_OPENGL_SHADERS
if (state.shadersAvailable())
{
if (fill.isColour())
{
setSolidColourShader();
state.fillEdgeTable (et, fill.colour.getPixelARGB());
state.setShader (nullptr);
return;
}
else if (fill.isGradient())
{
PositionedTexture pt (mask.getTextureID(), getMaskArea(), r);
state.setShaderForGradientFill (fill, &pt);
state.fillEdgeTable (et, fill.colour.getPixelARGB());
state.setShader (nullptr);
return;
}
}
#endif
OpenGLTexture* texture = state.getTexture (r.getWidth(), r.getHeight());
PositionedTexture pt1 (*texture, et, r);
PositionedTexture pt2 (mask.getTextureID(), getMaskArea(), r);
@ -1619,6 +1798,27 @@ public:
void fillRectInternal (const Rectangle<int>& area, const FillType& fill, bool replaceContents)
{
#if JUCE_USE_OPENGL_SHADERS
if (state.shadersAvailable())
{
if (fill.isColour())
{
setSolidColourShader();
state.fillRect (area, fill.colour.getPixelARGB());
state.setShader (nullptr);
return;
}
else if (fill.isGradient())
{
PositionedTexture pt (mask.getTextureID(), getMaskArea(), area);
state.setShaderForGradientFill (fill, &pt);
state.fillRect (area, fill.colour.getPixelARGB());
state.setShader (nullptr);
return;
}
}
#endif
PositionedTexture pt (mask.getTextureID(), getMaskArea(), area);
state.fillTexture (area, fill, &pt, nullptr, replaceContents);
}
@ -1664,6 +1864,21 @@ private:
prepareFor2D();
}
#if JUCE_USE_OPENGL_SHADERS
void setSolidColourShader()
{
state.setSolidColour();
state.setPremultipliedBlendingMode();
state.setSingleTextureMode();
state.bindTexture (mask.getTextureID());
state.setShader (programs->solidColourMasked);
programs->solidColourMasked.maskParams.maskBounds.set (maskOrigin.x - state.target.x,
state.target.height - (maskOrigin.y + mask.getHeight() - state.target.y),
mask.getWidth(), mask.getHeight());
}
#endif
struct FloatRectangleRenderer
{
FloatRectangleRenderer (ClipRegion_Mask& mask_, const FillType& fill_) noexcept
@ -1726,7 +1941,7 @@ public:
#if JUCE_USE_OPENGL_SHADERS
else if (state.shadersAvailable() && fill.isGradient())
{
state.setShaderForGradientFill (fill);
state.setShaderForGradientFill (fill, nullptr);
state.fillRectangleList (clip, area, fill.colour.getPixelARGB());
state.setShader (nullptr);
}
@ -1760,7 +1975,7 @@ public:
#if JUCE_USE_OPENGL_SHADERS
else if (state.shadersAvailable() && fill.isGradient())
{
state.setShaderForGradientFill (fill);
state.setShaderForGradientFill (fill, nullptr);
for (RectangleList::Iterator i (clip); i.next();)
{
@ -1811,7 +2026,7 @@ public:
#if JUCE_USE_OPENGL_SHADERS
else if (state.shadersAvailable() && fill.isGradient())
{
state.setShaderForGradientFill (fill);
state.setShaderForGradientFill (fill, nullptr);
if (clip.containsRectangle (et.getMaximumBounds()))
{
@ -1859,7 +2074,7 @@ private:
class OpenGLRenderer::SavedState
{
public:
SavedState (GLState* const state_)
SavedState (OpenGLRenderer::GLState* const state_)
: clip (new ClipRegion_RectangleList (*state_, Rectangle<int> (state_->target.width, state_->target.height))),
transform (0, 0), interpolationQuality (Graphics::mediumResamplingQuality),
state (state_), transparencyLayerAlpha (1.0f)