|
|
@@ -259,10 +259,9 @@ struct Target |
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class PositionedTexture
|
|
|
|
struct PositionedTexture
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PositionedTexture (OpenGLTexture& texture, const EdgeTable& et, const Rectangle<int>& clipRegion)
|
|
|
|
PositionedTexture (OpenGLTexture& texture, const EdgeTable& et, Rectangle<int> clipRegion)
|
|
|
|
: clip (clipRegion.getIntersection (et.getMaximumBounds()))
|
|
|
|
{
|
|
|
|
if (clip.contains (et.getMaximumBounds()))
|
|
|
@@ -277,7 +276,7 @@ public: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PositionedTexture (GLuint texture, const Rectangle<int> r, const Rectangle<int> clipRegion) noexcept
|
|
|
|
PositionedTexture (GLuint texture, Rectangle<int> r, Rectangle<int> clipRegion) noexcept
|
|
|
|
: textureID (texture), area (r), clip (clipRegion)
|
|
|
|
{}
|
|
|
|
|
|
|
@@ -328,6 +327,24 @@ private: |
|
|
|
memset (currentLine + x, 255, (size_t) width);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
|
|
|
|
{
|
|
|
|
while (--height >= 0)
|
|
|
|
{
|
|
|
|
setEdgeTableYPos (y++);
|
|
|
|
handleEdgeTableLine (x, width, alphaLevel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
|
|
|
|
{
|
|
|
|
while (--height >= 0)
|
|
|
|
{
|
|
|
|
setEdgeTableYPos (y++);
|
|
|
|
handleEdgeTableLineFull (x, width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapBlock<uint8> data;
|
|
|
|
const Rectangle<int> area;
|
|
|
|
|
|
|
@@ -339,9 +356,8 @@ private: |
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class ShaderPrograms : public ReferenceCountedObject
|
|
|
|
struct ShaderPrograms : public ReferenceCountedObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ShaderPrograms (OpenGLContext& context)
|
|
|
|
: solidColourProgram (context),
|
|
|
|
solidColourMasked (context),
|
|
|
@@ -409,7 +425,7 @@ public: |
|
|
|
screenBounds (program, "screenBounds")
|
|
|
|
{}
|
|
|
|
|
|
|
|
void set2DBounds (const Rectangle<float>& bounds)
|
|
|
|
void set2DBounds (Rectangle<float> bounds)
|
|
|
|
{
|
|
|
|
screenBounds.set (bounds.getX(), bounds.getY(), 0.5f * bounds.getWidth(), 0.5f * bounds.getHeight());
|
|
|
|
}
|
|
|
@@ -441,7 +457,7 @@ public: |
|
|
|
maskBounds (program, "maskBounds")
|
|
|
|
{}
|
|
|
|
|
|
|
|
void setBounds (const Rectangle<int>& area, const Target& target, const GLint textureIndex) const
|
|
|
|
void setBounds (Rectangle<int> area, const Target& target, GLint textureIndex) const
|
|
|
|
{
|
|
|
|
maskTexture.set (textureIndex);
|
|
|
|
maskBounds.set (area.getX() - target.bounds.getX(),
|
|
|
@@ -492,11 +508,11 @@ public: |
|
|
|
matrix (program, "matrix")
|
|
|
|
{}
|
|
|
|
|
|
|
|
void setMatrix (const Point<float> p1, const Point<float> p2, const Point<float> p3)
|
|
|
|
void setMatrix (Point<float> p1, Point<float> p2, Point<float> p3)
|
|
|
|
{
|
|
|
|
const AffineTransform t (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));
|
|
|
|
auto t = 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);
|
|
|
|
const GLfloat m[] = { t.mat00, t.mat01, t.mat02, t.mat10, t.mat11, t.mat12 };
|
|
|
|
matrix.set (m, 6);
|
|
|
|
}
|
|
|
@@ -637,15 +653,13 @@ public: |
|
|
|
imageLimits (program, "imageLimits")
|
|
|
|
{}
|
|
|
|
|
|
|
|
void setMatrix (const AffineTransform& trans,
|
|
|
|
const int imageWidth, const int imageHeight,
|
|
|
|
void setMatrix (const AffineTransform& trans, int imageWidth, int imageHeight,
|
|
|
|
float fullWidthProportion, float fullHeightProportion,
|
|
|
|
const float targetX, const float targetY,
|
|
|
|
const bool isForTiling) const
|
|
|
|
float targetX, float targetY, bool isForTiling) const
|
|
|
|
{
|
|
|
|
const AffineTransform t (trans.translated (-targetX, -targetY)
|
|
|
|
.inverted().scaled (fullWidthProportion / imageWidth,
|
|
|
|
fullHeightProportion / imageHeight));
|
|
|
|
auto t = trans.translated (-targetX, -targetY)
|
|
|
|
.inverted().scaled (fullWidthProportion / imageWidth,
|
|
|
|
fullHeightProportion / imageHeight);
|
|
|
|
|
|
|
|
const GLfloat m[] = { t.mat00, t.mat01, t.mat02, t.mat10, t.mat11, t.mat12 };
|
|
|
|
matrix.set (m, 6);
|
|
|
@@ -660,8 +674,7 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
void setMatrix (const AffineTransform& trans, const TextureInfo& textureInfo,
|
|
|
|
const float targetX, const float targetY,
|
|
|
|
bool isForTiling) const
|
|
|
|
float targetX, float targetY, bool isForTiling) const
|
|
|
|
{
|
|
|
|
setMatrix (trans,
|
|
|
|
textureInfo.imageWidth, textureInfo.imageHeight,
|
|
|
@@ -828,13 +841,13 @@ struct StateHelpers |
|
|
|
srcFunction = dstFunction = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setPremultipliedBlendingMode (QuadQueueType& quadQueue) noexcept
|
|
|
|
{
|
|
|
|
setBlendFunc (quadQueue, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setBlendFunc (QuadQueueType& quadQueue, GLenum src, GLenum dst)
|
|
|
|
{
|
|
|
|
if (! blendingEnabled)
|
|
|
@@ -853,7 +866,7 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void disableBlend (QuadQueueType& quadQueue) noexcept
|
|
|
|
{
|
|
|
|
if (blendingEnabled)
|
|
|
@@ -864,8 +877,8 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
void setBlendMode (QuadQueueType& quadQueue, const bool replaceExistingContents) noexcept
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setBlendMode (QuadQueueType& quadQueue, bool replaceExistingContents) noexcept
|
|
|
|
{
|
|
|
|
if (replaceExistingContents)
|
|
|
|
disableBlend (quadQueue);
|
|
|
@@ -879,42 +892,54 @@ struct StateHelpers |
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
struct EdgeTableRenderer
|
|
|
|
{
|
|
|
|
EdgeTableRenderer (QuadQueueType& q, const PixelARGB c) noexcept
|
|
|
|
EdgeTableRenderer (QuadQueueType& q, PixelARGB c) noexcept
|
|
|
|
: quadQueue (q), colour (c)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void setEdgeTableYPos (const int y) noexcept
|
|
|
|
void setEdgeTableYPos (int y) noexcept
|
|
|
|
{
|
|
|
|
currentY = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTablePixel (const int x, const int alphaLevel) noexcept
|
|
|
|
void handleEdgeTablePixel (int x, int alphaLevel) noexcept
|
|
|
|
{
|
|
|
|
PixelARGB c (colour);
|
|
|
|
auto c = colour;
|
|
|
|
c.multiplyAlpha (alphaLevel);
|
|
|
|
quadQueue.add (x, currentY, 1, 1, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTablePixelFull (const int x) noexcept
|
|
|
|
void handleEdgeTablePixelFull (int x) noexcept
|
|
|
|
{
|
|
|
|
quadQueue.add (x, currentY, 1, 1, colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableLine (const int x, const int width, const int alphaLevel) noexcept
|
|
|
|
void handleEdgeTableLine (int x, int width, int alphaLevel) noexcept
|
|
|
|
{
|
|
|
|
PixelARGB c (colour);
|
|
|
|
auto c = colour;
|
|
|
|
c.multiplyAlpha (alphaLevel);
|
|
|
|
quadQueue.add (x, currentY, width, 1, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableLineFull (const int x, const int width) noexcept
|
|
|
|
void handleEdgeTableLineFull (int x, int width) noexcept
|
|
|
|
{
|
|
|
|
quadQueue.add (x, currentY, width, 1, colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
|
|
|
|
{
|
|
|
|
auto c = colour;
|
|
|
|
c.multiplyAlpha (alphaLevel);
|
|
|
|
quadQueue.add (x, y, width, height, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
|
|
|
|
{
|
|
|
|
quadQueue.add (x, y, width, height, colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
QuadQueueType& quadQueue;
|
|
|
|
const PixelARGB colour;
|
|
|
@@ -923,14 +948,14 @@ struct StateHelpers |
|
|
|
JUCE_DECLARE_NON_COPYABLE (EdgeTableRenderer)
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
struct FloatRectangleRenderer
|
|
|
|
{
|
|
|
|
FloatRectangleRenderer (QuadQueueType& q, const PixelARGB c) noexcept
|
|
|
|
FloatRectangleRenderer (QuadQueueType& q, PixelARGB c) noexcept
|
|
|
|
: quadQueue (q), colour (c)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void operator() (const int x, const int y, const int w, const int h, const int alpha) noexcept
|
|
|
|
void operator() (int x, int y, int w, int h, int alpha) noexcept
|
|
|
|
{
|
|
|
|
if (w > 0 && h > 0)
|
|
|
|
{
|
|
|
@@ -959,8 +984,8 @@ struct StateHelpers |
|
|
|
zeromem (currentTextureID, sizeof (currentTextureID));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
void setTexturesEnabled (QuadQueueType& quadQueue, const int textureIndexMask) noexcept
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setTexturesEnabled (QuadQueueType& quadQueue, int textureIndexMask) noexcept
|
|
|
|
{
|
|
|
|
if (texturesEnabled != textureIndexMask)
|
|
|
|
{
|
|
|
@@ -991,20 +1016,20 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void disableTextures (QuadQueueType& quadQueue) noexcept
|
|
|
|
{
|
|
|
|
setTexturesEnabled (quadQueue, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setSingleTextureMode (QuadQueueType& quadQueue) noexcept
|
|
|
|
{
|
|
|
|
setTexturesEnabled (quadQueue, 1);
|
|
|
|
setActiveTexture (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class QuadQueueType>
|
|
|
|
template <typename QuadQueueType>
|
|
|
|
void setTwoTextureMode (QuadQueueType& quadQueue, GLuint texture1, GLuint texture2)
|
|
|
|
{
|
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
@@ -1026,7 +1051,7 @@ struct StateHelpers |
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
}
|
|
|
|
|
|
|
|
void setActiveTexture (const int index) noexcept
|
|
|
|
void setActiveTexture (int index) noexcept
|
|
|
|
{
|
|
|
|
if (currentActiveTexture != index)
|
|
|
|
{
|
|
|
@@ -1036,13 +1061,13 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void bindTexture (const GLuint textureID) noexcept
|
|
|
|
void bindTexture (GLuint textureID) noexcept
|
|
|
|
{
|
|
|
|
jassert (currentActiveTexture >= 0);
|
|
|
|
|
|
|
|
if (currentTextureID [currentActiveTexture] != textureID)
|
|
|
|
if (currentTextureID[currentActiveTexture] != textureID)
|
|
|
|
{
|
|
|
|
currentTextureID [currentActiveTexture] = textureID;
|
|
|
|
currentTextureID[currentActiveTexture] = textureID;
|
|
|
|
glBindTexture (GL_TEXTURE_2D, textureID);
|
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
}
|
|
|
@@ -1057,7 +1082,7 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GLuint currentTextureID [3];
|
|
|
|
GLuint currentTextureID[3];
|
|
|
|
int texturesEnabled, currentActiveTexture;
|
|
|
|
const OpenGLContext& context;
|
|
|
|
|
|
|
@@ -1067,9 +1092,7 @@ struct StateHelpers |
|
|
|
//==============================================================================
|
|
|
|
struct TextureCache
|
|
|
|
{
|
|
|
|
TextureCache() noexcept
|
|
|
|
: activeGradientIndex (0), gradientNeedsRefresh (true)
|
|
|
|
{}
|
|
|
|
TextureCache() noexcept {}
|
|
|
|
|
|
|
|
OpenGLTexture* getTexture (ActiveTextures& activeTextures, int w, int h)
|
|
|
|
{
|
|
|
@@ -1081,7 +1104,8 @@ struct StateHelpers |
|
|
|
|
|
|
|
for (int i = 0; i < numTexturesToCache - 2; ++i)
|
|
|
|
{
|
|
|
|
const OpenGLTexture* const t = textures.getUnchecked(i);
|
|
|
|
auto* t = textures.getUnchecked(i);
|
|
|
|
|
|
|
|
if (t->getWidth() == w && t->getHeight() == h)
|
|
|
|
return textures.removeAndReturn (i);
|
|
|
|
}
|
|
|
@@ -1112,7 +1136,7 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
|
|
|
|
JUCE_CHECK_OPENGL_ERROR;
|
|
|
|
PixelARGB lookup [gradientTextureSize];
|
|
|
|
PixelARGB lookup[gradientTextureSize];
|
|
|
|
gradient.createLookupTable (lookup, gradientTextureSize);
|
|
|
|
gradientTextures.getUnchecked (activeGradientIndex)->loadARGB (lookup, gradientTextureSize, 1);
|
|
|
|
}
|
|
|
@@ -1125,15 +1149,14 @@ struct StateHelpers |
|
|
|
private:
|
|
|
|
enum { numTexturesToCache = 8, numGradientTexturesToCache = 10 };
|
|
|
|
OwnedArray<OpenGLTexture> textures, gradientTextures;
|
|
|
|
int activeGradientIndex;
|
|
|
|
bool gradientNeedsRefresh;
|
|
|
|
int activeGradientIndex = 0;
|
|
|
|
bool gradientNeedsRefresh = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
struct ShaderQuadQueue
|
|
|
|
{
|
|
|
|
ShaderQuadQueue (const OpenGLContext& c) noexcept
|
|
|
|
: context (c), numVertices (0)
|
|
|
|
ShaderQuadQueue (const OpenGLContext& c) noexcept : context (c)
|
|
|
|
{}
|
|
|
|
|
|
|
|
~ShaderQuadQueue() noexcept
|
|
|
@@ -1147,6 +1170,7 @@ struct StateHelpers |
|
|
|
void initialise() noexcept
|
|
|
|
{
|
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
|
|
|
|
for (int i = 0, v = 0; i < numQuads * 6; i += 6, v += 4)
|
|
|
|
{
|
|
|
|
indexData[i] = (GLushort) v;
|
|
|
@@ -1163,22 +1187,22 @@ struct StateHelpers |
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
}
|
|
|
|
|
|
|
|
void add (const int x, const int y, const int w, const int h, const PixelARGB colour) noexcept
|
|
|
|
void add (int x, int y, int w, int h, PixelARGB colour) noexcept
|
|
|
|
{
|
|
|
|
jassert (w > 0 && h > 0);
|
|
|
|
|
|
|
|
VertexInfo* const v = vertexData + numVertices;
|
|
|
|
auto* v = vertexData + numVertices;
|
|
|
|
v[0].x = v[2].x = (GLshort) x;
|
|
|
|
v[0].y = v[1].y = (GLshort) y;
|
|
|
|
v[1].x = v[3].x = (GLshort) (x + w);
|
|
|
|
v[2].y = v[3].y = (GLshort) (y + h);
|
|
|
|
|
|
|
|
#if JUCE_BIG_ENDIAN
|
|
|
|
const GLuint rgba = (GLuint) ((colour.getRed() << 24) | (colour.getGreen() << 16)
|
|
|
|
| (colour.getBlue() << 8) | colour.getAlpha());
|
|
|
|
auto rgba = (GLuint) ((colour.getRed() << 24) | (colour.getGreen() << 16)
|
|
|
|
| (colour.getBlue() << 8) | colour.getAlpha());
|
|
|
|
#else
|
|
|
|
const GLuint rgba = (GLuint) ((colour.getAlpha() << 24) | (colour.getBlue() << 16)
|
|
|
|
| (colour.getGreen() << 8) | colour.getRed());
|
|
|
|
auto rgba = (GLuint) ((colour.getAlpha() << 24) | (colour.getBlue() << 16)
|
|
|
|
| (colour.getGreen() << 8) | colour.getRed());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
v[0].colour = rgba;
|
|
|
@@ -1192,24 +1216,24 @@ struct StateHelpers |
|
|
|
draw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void add (const Rectangle<int>& r, const PixelARGB colour) noexcept
|
|
|
|
void add (Rectangle<int> r, PixelARGB colour) noexcept
|
|
|
|
{
|
|
|
|
add (r.getX(), r.getY(), r.getWidth(), r.getHeight(), colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
void add (const Rectangle<float>& r, const PixelARGB colour) noexcept
|
|
|
|
void add (Rectangle<float> r, PixelARGB colour) noexcept
|
|
|
|
{
|
|
|
|
FloatRectangleRenderer<ShaderQuadQueue> frr (*this, colour);
|
|
|
|
RenderingHelpers::FloatRectangleRasterisingInfo (r).iterate (frr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void add (const RectangleList<int>& list, const PixelARGB colour) noexcept
|
|
|
|
void add (const RectangleList<int>& list, PixelARGB colour) noexcept
|
|
|
|
{
|
|
|
|
for (auto& i : list)
|
|
|
|
add (i, colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
void add (const RectangleList<int>& list, const Rectangle<int>& clip, const PixelARGB colour) noexcept
|
|
|
|
void add (const RectangleList<int>& list, Rectangle<int> clip, PixelARGB colour) noexcept
|
|
|
|
{
|
|
|
|
for (auto& i : list)
|
|
|
|
{
|
|
|
@@ -1220,8 +1244,8 @@ struct StateHelpers |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class IteratorType>
|
|
|
|
void add (const IteratorType& et, const PixelARGB colour)
|
|
|
|
template <typename IteratorType>
|
|
|
|
void add (const IteratorType& et, PixelARGB colour)
|
|
|
|
{
|
|
|
|
EdgeTableRenderer<ShaderQuadQueue> etr (*this, colour);
|
|
|
|
et.iterate (etr);
|
|
|
@@ -1243,10 +1267,10 @@ struct StateHelpers |
|
|
|
enum { numQuads = 256 };
|
|
|
|
|
|
|
|
GLuint buffers[2];
|
|
|
|
VertexInfo vertexData [numQuads * 4];
|
|
|
|
GLushort indexData [numQuads * 6];
|
|
|
|
VertexInfo vertexData[numQuads * 4];
|
|
|
|
GLushort indexData[numQuads * 6];
|
|
|
|
const OpenGLContext& context;
|
|
|
|
int numVertices;
|
|
|
|
int numVertices = 0;
|
|
|
|
|
|
|
|
void draw() noexcept
|
|
|
|
{
|
|
|
@@ -1264,10 +1288,9 @@ struct StateHelpers |
|
|
|
//==============================================================================
|
|
|
|
struct CurrentShader
|
|
|
|
{
|
|
|
|
CurrentShader (OpenGLContext& c) noexcept
|
|
|
|
: context (c), activeShader (nullptr)
|
|
|
|
CurrentShader (OpenGLContext& c) noexcept : context (c)
|
|
|
|
{
|
|
|
|
const char programValueID[] = "GraphicsContextPrograms";
|
|
|
|
auto programValueID = "GraphicsContextPrograms";
|
|
|
|
programs = static_cast<ShaderPrograms*> (context.getAssociatedObject (programValueID));
|
|
|
|
|
|
|
|
if (programs == nullptr)
|
|
|
@@ -1282,7 +1305,7 @@ struct StateHelpers |
|
|
|
jassert (activeShader == nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setShader (const Rectangle<int>& bounds, ShaderQuadQueue& quadQueue, ShaderPrograms::ShaderBase& shader)
|
|
|
|
void setShader (Rectangle<int> bounds, ShaderQuadQueue& quadQueue, ShaderPrograms::ShaderBase& shader)
|
|
|
|
{
|
|
|
|
if (activeShader != &shader)
|
|
|
|
{
|
|
|
@@ -1324,7 +1347,7 @@ struct StateHelpers |
|
|
|
ShaderPrograms::Ptr programs;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ShaderPrograms::ShaderBase* activeShader;
|
|
|
|
ShaderPrograms::ShaderBase* activeShader = nullptr;
|
|
|
|
Rectangle<int> currentBounds;
|
|
|
|
|
|
|
|
CurrentShader& operator= (const CurrentShader&);
|
|
|
@@ -1332,9 +1355,8 @@ struct StateHelpers |
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class GLState
|
|
|
|
struct GLState
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
GLState (const Target& t) noexcept
|
|
|
|
: target (t),
|
|
|
|
activeTextures (t.context),
|
|
|
@@ -1375,7 +1397,7 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
void setShaderForGradientFill (const ColourGradient& g, const AffineTransform& transform,
|
|
|
|
const int maskTextureID, const Rectangle<int>* const maskArea)
|
|
|
|
int maskTextureID, const Rectangle<int>* maskArea)
|
|
|
|
{
|
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
activeTextures.disableTextures (shaderQuadQueue);
|
|
|
@@ -1396,12 +1418,12 @@ public: |
|
|
|
textureCache.bindTextureForGradient (activeTextures, g);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AffineTransform t (transform.translated (0.5f - target.bounds.getX(),
|
|
|
|
0.5f - target.bounds.getY()));
|
|
|
|
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));
|
|
|
|
auto t = transform.translated (0.5f - target.bounds.getX(),
|
|
|
|
0.5f - target.bounds.getY());
|
|
|
|
auto p1 = g.point1.transformedBy (t);
|
|
|
|
auto p2 = g.point2.transformedBy (t);
|
|
|
|
auto p3 = Point<float> (g.point1.x + (g.point2.y - g.point1.y),
|
|
|
|
g.point1.y - (g.point2.x - g.point1.x)).transformedBy (t);
|
|
|
|
|
|
|
|
ShaderPrograms* const programs = currentShader.programs;
|
|
|
|
const ShaderPrograms::MaskedShaderParams* maskParams = nullptr;
|
|
|
@@ -1476,7 +1498,7 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
void setShaderForTiledImageFill (const TextureInfo& textureInfo, const AffineTransform& transform,
|
|
|
|
const int maskTextureID, const Rectangle<int>* const maskArea, bool isTiledFill)
|
|
|
|
int maskTextureID, const Rectangle<int>* maskArea, bool isTiledFill)
|
|
|
|
{
|
|
|
|
blendMode.setPremultipliedBlendingMode (shaderQuadQueue);
|
|
|
|
|
|
|
@@ -1540,29 +1562,26 @@ private: |
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class SavedState : public RenderingHelpers::SavedStateBase<SavedState>
|
|
|
|
struct SavedState : public RenderingHelpers::SavedStateBase<SavedState>
|
|
|
|
{
|
|
|
|
typedef RenderingHelpers::SavedStateBase<SavedState> BaseClass;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SavedState (GLState* const s)
|
|
|
|
: BaseClass (s->target.bounds), state (s), isUsingCustomShader (false)
|
|
|
|
SavedState (GLState* s) : BaseClass (s->target.bounds), state (s)
|
|
|
|
{}
|
|
|
|
|
|
|
|
SavedState (const SavedState& other)
|
|
|
|
: BaseClass (other), font (other.font),
|
|
|
|
state (other.state), isUsingCustomShader (false),
|
|
|
|
: BaseClass (other), font (other.font), state (other.state),
|
|
|
|
transparencyLayer (other.transparencyLayer),
|
|
|
|
previousTarget (other.previousTarget.createCopy())
|
|
|
|
{}
|
|
|
|
|
|
|
|
SavedState* beginTransparencyLayer (float opacity)
|
|
|
|
{
|
|
|
|
SavedState* const s = new SavedState (*this);
|
|
|
|
auto* s = new SavedState (*this);
|
|
|
|
|
|
|
|
if (clip != nullptr)
|
|
|
|
{
|
|
|
|
const Rectangle<int> clipBounds (clip->getClipBounds());
|
|
|
|
auto clipBounds = clip->getClipBounds();
|
|
|
|
|
|
|
|
state->flush();
|
|
|
|
s->transparencyLayer = Image (OpenGLImageType().create (Image::ARGB, clipBounds.getWidth(), clipBounds.getHeight(), true));
|
|
|
@@ -1588,7 +1607,7 @@ public: |
|
|
|
finishedLayerState.previousTarget.reset();
|
|
|
|
|
|
|
|
state->target.makeActive();
|
|
|
|
const Rectangle<int> clipBounds (clip->getClipBounds());
|
|
|
|
auto clipBounds = clip->getClipBounds();
|
|
|
|
|
|
|
|
clip->renderImageUntransformed (*this, finishedLayerState.transparencyLayer,
|
|
|
|
(int) (finishedLayerState.transparencyLayerAlpha * 255.0f),
|
|
|
@@ -1604,8 +1623,7 @@ public: |
|
|
|
{
|
|
|
|
if (trans.isOnlyTranslation() && ! transform.isRotated)
|
|
|
|
{
|
|
|
|
GlyphCacheType& cache = GlyphCacheType::getInstance();
|
|
|
|
|
|
|
|
auto& cache = GlyphCacheType::getInstance();
|
|
|
|
Point<float> pos (trans.getTranslationX(), trans.getTranslationY());
|
|
|
|
|
|
|
|
if (transform.isOnlyTranslated)
|
|
|
@@ -1619,7 +1637,8 @@ public: |
|
|
|
Font f (font);
|
|
|
|
f.setHeight (font.getHeight() * transform.complexTransform.mat11);
|
|
|
|
|
|
|
|
const float xScale = transform.complexTransform.mat00 / transform.complexTransform.mat11;
|
|
|
|
auto xScale = transform.complexTransform.mat00 / transform.complexTransform.mat11;
|
|
|
|
|
|
|
|
if (std::abs (xScale - 1.0f) > 0.01f)
|
|
|
|
f.setHorizontalScale (xScale);
|
|
|
|
|
|
|
@@ -1628,10 +1647,10 @@ public: |
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const float fontHeight = font.getHeight();
|
|
|
|
auto fontHeight = font.getHeight();
|
|
|
|
|
|
|
|
AffineTransform t (transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
|
|
|
.followedBy (trans)));
|
|
|
|
auto t = transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
|
|
|
.followedBy (trans));
|
|
|
|
|
|
|
|
const ScopedPointer<EdgeTable> et (font.getTypeface()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
|
|
|
|
|
|
|
@@ -1651,7 +1670,7 @@ public: |
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
template <typename IteratorType>
|
|
|
|
void renderImageTransformed (IteratorType& iter, const Image& src, const int alpha,
|
|
|
|
void renderImageTransformed (IteratorType& iter, const Image& src, int alpha,
|
|
|
|
const AffineTransform& trans, Graphics::ResamplingQuality, bool tiledFill) const
|
|
|
|
{
|
|
|
|
state->shaderQuadQueue.flush();
|
|
|
@@ -1664,14 +1683,14 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IteratorType>
|
|
|
|
void renderImageUntransformed (IteratorType& iter, const Image& src, const int alpha, int x, int y, bool tiledFill) const
|
|
|
|
void renderImageUntransformed (IteratorType& iter, const Image& src, int alpha, int x, int y, bool tiledFill) const
|
|
|
|
{
|
|
|
|
renderImageTransformed (iter, src, alpha, AffineTransform::translation ((float) x, (float) y),
|
|
|
|
Graphics::lowResamplingQuality, tiledFill);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IteratorType>
|
|
|
|
void fillWithSolidColour (IteratorType& iter, const PixelARGB colour, bool replaceContents) const
|
|
|
|
void fillWithSolidColour (IteratorType& iter, PixelARGB colour, bool replaceContents) const
|
|
|
|
{
|
|
|
|
if (! isUsingCustomShader)
|
|
|
|
{
|
|
|
@@ -1690,7 +1709,7 @@ public: |
|
|
|
state->shaderQuadQueue.add (iter, fillType.colour.getPixelARGB());
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillRectWithCustomShader (OpenGLRendering::ShaderPrograms::ShaderBase& shader, const Rectangle<int>& area)
|
|
|
|
void fillRectWithCustomShader (OpenGLRendering::ShaderPrograms::ShaderBase& shader, Rectangle<int> area)
|
|
|
|
{
|
|
|
|
state->setShader (shader);
|
|
|
|
isUsingCustomShader = true;
|
|
|
@@ -1704,7 +1723,7 @@ public: |
|
|
|
//==============================================================================
|
|
|
|
Font font;
|
|
|
|
GLState* state;
|
|
|
|
bool isUsingCustomShader;
|
|
|
|
bool isUsingCustomShader = false;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Image transparencyLayer;
|
|
|
@@ -1715,15 +1734,14 @@ private: |
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class ShaderContext : public RenderingHelpers::StackBasedLowLevelGraphicsContext<SavedState>
|
|
|
|
struct ShaderContext : public RenderingHelpers::StackBasedLowLevelGraphicsContext<SavedState>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ShaderContext (const Target& target) : glState (target)
|
|
|
|
{
|
|
|
|
stack.initialise (new SavedState (&glState));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillRectWithCustomShader (ShaderPrograms::ShaderBase& shader, const Rectangle<int>& area)
|
|
|
|
void fillRectWithCustomShader (ShaderPrograms::ShaderBase& shader, Rectangle<int> area)
|
|
|
|
{
|
|
|
|
static_cast<SavedState&> (*stack).fillRectWithCustomShader (shader, area);
|
|
|
|
}
|
|
|
@@ -1733,9 +1751,8 @@ public: |
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ShaderContext)
|
|
|
|
};
|
|
|
|
|
|
|
|
class NonShaderContext : public LowLevelGraphicsSoftwareRenderer
|
|
|
|
struct NonShaderContext : public LowLevelGraphicsSoftwareRenderer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NonShaderContext (const Target& t, const Image& im)
|
|
|
|
: LowLevelGraphicsSoftwareRenderer (im), target (t), image (im)
|
|
|
|
{}
|
|
|
@@ -1743,7 +1760,7 @@ public: |
|
|
|
~NonShaderContext()
|
|
|
|
{
|
|
|
|
JUCE_CHECK_OPENGL_ERROR
|
|
|
|
const GLuint previousFrameBufferTarget = OpenGLFrameBuffer::getCurrentFrameBufferTarget();
|
|
|
|
auto previousFrameBufferTarget = OpenGLFrameBuffer::getCurrentFrameBufferTarget();
|
|
|
|
|
|
|
|
#if ! JUCE_ANDROID
|
|
|
|
target.context.extensions.glActiveTexture (GL_TEXTURE0);
|
|
|
@@ -1803,7 +1820,7 @@ LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context, in |
|
|
|
|
|
|
|
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context, OpenGLFrameBuffer& target)
|
|
|
|
{
|
|
|
|
return OpenGLRendering::createOpenGLContext (OpenGLRendering::Target (context, target, Point<int>()));
|
|
|
|
return OpenGLRendering::createOpenGLContext (OpenGLRendering::Target (context, target, {}));
|
|
|
|
}
|
|
|
|
|
|
|
|
LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context, unsigned int frameBufferID, int width, int height)
|
|
|
@@ -1822,7 +1839,7 @@ struct CustomProgram : public ReferenceCountedObject, |
|
|
|
|
|
|
|
static CustomProgram* get (const String& hashName)
|
|
|
|
{
|
|
|
|
if (OpenGLContext* c = OpenGLContext::getCurrentContext())
|
|
|
|
if (auto* c = OpenGLContext::getCurrentContext())
|
|
|
|
return static_cast<CustomProgram*> (c->getAssociatedObject (hashName.toRawUTF8()));
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
@@ -1830,13 +1847,12 @@ struct CustomProgram : public ReferenceCountedObject, |
|
|
|
|
|
|
|
static CustomProgram* getOrCreate (LowLevelGraphicsContext& gc, const String& hashName, const String& code, String& errorMessage)
|
|
|
|
{
|
|
|
|
if (CustomProgram* c = get (hashName))
|
|
|
|
if (auto* c = get (hashName))
|
|
|
|
return c;
|
|
|
|
|
|
|
|
if (OpenGLRendering::ShaderContext* sc = dynamic_cast<OpenGLRendering::ShaderContext*> (&gc))
|
|
|
|
if (auto* sc = dynamic_cast<OpenGLRendering::ShaderContext*> (&gc))
|
|
|
|
{
|
|
|
|
ReferenceCountedObjectPtr<CustomProgram> c (new CustomProgram (*sc, code));
|
|
|
|
|
|
|
|
errorMessage = c->lastError;
|
|
|
|
|
|
|
|
if (errorMessage.isEmpty())
|
|
|
@@ -1879,7 +1895,7 @@ OpenGLShaderProgram* OpenGLGraphicsContextCustomShader::getProgram (LowLevelGrap |
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLGraphicsContextCustomShader::fillRect (LowLevelGraphicsContext& gc, const Rectangle<int>& area) const
|
|
|
|
void OpenGLGraphicsContextCustomShader::fillRect (LowLevelGraphicsContext& gc, Rectangle<int> area) const
|
|
|
|
{
|
|
|
|
String errorMessage;
|
|
|
|
|
|
|
|