Browse Source

ImageButton fix. OpenGL refactoring.

tags/2021-05-28
jules 14 years ago
parent
commit
b23e5c4515
14 changed files with 136 additions and 300 deletions
  1. +1
    -1
      modules/juce_core/native/juce_posix_SharedCode.h
  2. +2
    -2
      modules/juce_graphics/native/juce_RenderingHelpers.h
  3. +8
    -6
      modules/juce_gui_basics/buttons/juce_ImageButton.cpp
  4. +5
    -0
      modules/juce_opengl/native/juce_android_OpenGLComponent.cpp
  5. +6
    -0
      modules/juce_opengl/native/juce_ios_OpenGLComponent.mm
  6. +7
    -0
      modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp
  7. +6
    -0
      modules/juce_opengl/native/juce_mac_OpenGLComponent.mm
  8. +6
    -0
      modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp
  9. +25
    -48
      modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp
  10. +0
    -13
      modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h
  11. +54
    -224
      modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp
  12. +12
    -1
      modules/juce_opengl/opengl/juce_OpenGLHelpers.h
  13. +0
    -5
      modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h
  14. +4
    -0
      modules/juce_opengl/opengl/juce_OpenGLTexture.cpp

+ 1
- 1
modules/juce_core/native/juce_posix_SharedCode.h View File

@@ -771,7 +771,7 @@ void InterProcessLock::exit()
//============================================================================== //==============================================================================
void JUCE_API juce_threadEntryPoint (void*); void JUCE_API juce_threadEntryPoint (void*);
void* threadEntryProc (void* userData)
extern "C" void* threadEntryProc (void* userData)
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL


+ 2
- 2
modules/juce_graphics/native/juce_RenderingHelpers.h View File

@@ -77,7 +77,7 @@ public:
{ {
if (isOnlyTranslated if (isOnlyTranslated
&& t.isOnlyTranslation() && t.isOnlyTranslation()
&& isIntegerTranlation (t))
&& isIntegerTranslation (t))
{ {
xOffset += (int) t.getTranslationX(); xOffset += (int) t.getTranslationX();
yOffset += (int) t.getTranslationY(); yOffset += (int) t.getTranslationY();
@@ -126,7 +126,7 @@ public:
bool isOnlyTranslated; bool isOnlyTranslated;
private: private:
static inline bool isIntegerTranlation (const AffineTransform& t) noexcept
static inline bool isIntegerTranslation (const AffineTransform& t) noexcept
{ {
const int tx = (int) (t.getTranslationX() * 256.0f); const int tx = (int) (t.getTranslationX() * 256.0f);
const int ty = (int) (t.getTranslationY() * 256.0f); const int ty = (int) (t.getTranslationY() * 256.0f);


+ 8
- 6
modules/juce_gui_basics/buttons/juce_ImageButton.cpp View File

@@ -129,16 +129,16 @@ void ImageButton::paintButton (Graphics& g,
const int ih = im.getHeight(); const int ih = im.getHeight();
imageW = getWidth(); imageW = getWidth();
imageH = getHeight(); imageH = getHeight();
imageX = (imageW - iw) >> 1;
imageY = (imageH - ih) >> 1;
imageX = (imageW - iw) / 2;
imageY = (imageH - ih) / 2;
if (scaleImageToFit) if (scaleImageToFit)
{ {
if (preserveProportions) if (preserveProportions)
{ {
int newW, newH; int newW, newH;
const float imRatio = ih / (float)iw;
const float destRatio = imageH / (float)imageW;
const float imRatio = ih / (float) iw;
const float destRatio = imageH / (float) imageW;
if (imRatio > destRatio) if (imRatio > destRatio)
{ {
@@ -169,11 +169,13 @@ void ImageButton::paintButton (Graphics& g,
imageH = ih; imageH = ih;
} }
const bool useDownImage = isButtonDown || getToggleState();
getLookAndFeel().drawImageButton (g, &im, imageX, imageY, imageW, imageH, getLookAndFeel().drawImageButton (g, &im, imageX, imageY, imageW, imageH,
isButtonDown ? downOverlay
useDownImage ? downOverlay
: (isMouseOverButton ? overOverlay : (isMouseOverButton ? overOverlay
: normalOverlay), : normalOverlay),
isButtonDown ? downOpacity
useDownImage ? downOpacity
: (isMouseOverButton ? overOpacity : (isMouseOverButton ? overOpacity
: normalOpacity), : normalOpacity),
*this); *this);


+ 5
- 0
modules/juce_opengl/native/juce_android_OpenGLComponent.cpp View File

@@ -39,3 +39,8 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component,
{ {
} }
bool OpenGLHelpers::isContextActive()
{
return false;
}

+ 6
- 0
modules/juce_opengl/native/juce_ios_OpenGLComponent.mm View File

@@ -234,3 +234,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
OwnedArray <OpenGLPixelFormat>& /*results*/) OwnedArray <OpenGLPixelFormat>& /*results*/)
{ {
} }
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return [EAGLContext currentContext] != nil;
}

+ 7
- 0
modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp View File

@@ -200,3 +200,10 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, OwnedArr
{ {
results.add (new OpenGLPixelFormat()); // xxx results.add (new OpenGLPixelFormat()); // xxx
} }
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
ScopedXLock xlock;
return glXGetCurrentContext() != 0;
}

+ 6
- 0
modules/juce_opengl/native/juce_mac_OpenGLComponent.mm View File

@@ -312,3 +312,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
results.add (pf); results.add (pf);
} }
} }
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return [NSOpenGLContext currentContext] != nil;
}

+ 6
- 0
modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp View File

@@ -509,3 +509,9 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component,
wc.findAlternativeOpenGLPixelFormats (results); wc.findAlternativeOpenGLPixelFormats (results);
} }
} }
//==============================================================================
bool OpenGLHelpers::isContextActive()
{
return wglGetCurrentContext() != 0;
}

+ 25
- 48
modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp View File

@@ -145,6 +145,10 @@ public:
hasStencilBuffer (false), hasStencilBuffer (false),
ok (false) ok (false)
{ {
// Framebuffer objects can only be created when the current thread has an active OpenGL
// context. You'll need to make an OpenGLComponent active before calling this.
jassert (OpenGLHelpers::isContextActive());
#if JUCE_WINDOWS || JUCE_LINUX #if JUCE_WINDOWS || JUCE_LINUX
initialiseFrameBufferFunctions(); initialiseFrameBufferFunctions();
@@ -155,17 +159,13 @@ public:
OpenGLHelpers::resetErrorState(); OpenGLHelpers::resetErrorState();
glGenFramebuffersEXT (1, &frameBufferHandle); glGenFramebuffersEXT (1, &frameBufferHandle);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferHandle); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferHandle);
glGenTextures (1, &textureID); glGenTextures (1, &textureID);
glBindTexture (textureType, textureID); glBindTexture (textureType, textureID);
glTexImage2D (textureType, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexImage2D (textureType, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf (textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (textureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf (textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, textureType, textureID, 0); glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, textureType, textureID, 0);
if (wantsDepthBuffer || wantsStencilBuffer) if (wantsDepthBuffer || wantsStencilBuffer)
@@ -174,37 +174,33 @@ public:
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, depthOrStencilBuffer); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, depthOrStencilBuffer);
jassert (glIsRenderbufferEXT (depthOrStencilBuffer)); jassert (glIsRenderbufferEXT (depthOrStencilBuffer));
if (wantsDepthBuffer && wantsStencilBuffer)
{
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT,
(wantsDepthBuffer && wantsStencilBuffer) ? GL_DEPTH24_STENCIL8_EXT
#if JUCE_OPENGL_ES
: GL_DEPTH_COMPONENT16,
#else
: GL_DEPTH_COMPONENT,
#endif
width, height);
GLint params = 0;
glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &params);
GLint params = 0;
glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &params);
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer);
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer);
if (wantsStencilBuffer)
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer); glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer);
hasDepthBuffer = true;
hasStencilBuffer = true;
}
else
{
#if JUCE_OPENGL_ES
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
#else
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
#endif
GLint params = 0;
glGetRenderbufferParameterivEXT (GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &params);
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthOrStencilBuffer);
hasDepthBuffer = true;
}
hasDepthBuffer = wantsDepthBuffer;
hasStencilBuffer = wantsStencilBuffer;
} }
ok = checkStatus(); ok = checkStatus();
glTexParameterf (textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (textureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf (textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
} }
@@ -438,7 +434,7 @@ bool OpenGLFrameBuffer::writePixels (const void* data, int pixelStride, const Re
glBindTexture (GL_TEXTURE_2D, temporaryTexture); glBindTexture (GL_TEXTURE_2D, temporaryTexture);
glPixelStorei (GL_UNPACK_ALIGNMENT, pixelStride); glPixelStorei (GL_UNPACK_ALIGNMENT, pixelStride);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, area.getWidth(), area.getHeight(), 0,
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, area.getWidth(), area.getHeight(), 0,
format, GL_UNSIGNED_BYTE, data); format, GL_UNSIGNED_BYTE, data);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -522,24 +518,5 @@ void OpenGLFrameBuffer::drawAt (float x1, float y1) const
} }
} }
//==============================================================================
void OpenGLFrameBuffer::createAlphaChannelFromPath (const Path& path, const AffineTransform& transform,
const int oversamplingLevel)
{
makeCurrentRenderingTarget();
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_NORMAL_ARRAY);
glDisable (GL_TEXTURE_2D);
glDisable (GL_DEPTH_TEST);
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
prepareFor2D();
TriangulatedPath (path, transform).draw (oversamplingLevel);
}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 0
- 13
modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.h View File

@@ -134,19 +134,6 @@ public:
bool writePixels (const void* srcData, int srcPixelStride, bool writePixels (const void* srcData, int srcPixelStride,
const Rectangle<int>& targetArea); const Rectangle<int>& targetArea);
/** This will render an anti-aliased path into just the alpha channel of this framebuffer.
The idea here is that you can clear a framebuffer, use this to set its alpha channel, then
fill the RGB channels with some kind of fill-pattern, and then copy the whole thing onto
a target, to produce a filled path with some kind of texture.
Calling this will make changes to a lot of openGL state, including colour masks, blend
functions, etc
*/
void createAlphaChannelFromPath (const Path& path,
const AffineTransform& transform,
int oversamplingLevel = 4);
private: private:
class Pimpl; class Pimpl;
friend class ScopedPointer<Pimpl>; friend class ScopedPointer<Pimpl>;


+ 54
- 224
modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp View File

@@ -51,7 +51,7 @@ void OpenGLHelpers::prepareFor2D (const int width, const int height)
glLoadIdentity(); glLoadIdentity();
#if JUCE_OPENGL_ES #if JUCE_OPENGL_ES
glOrthof (0.0f, (float) width, 0.0f, (float) height, 0.0f, 1.0f);
glOrthof (0.0f, (GLfloat) width, 0.0f, (GLfloat) height, 0.0f, 1.0f);
#else #else
glOrtho (0.0, width, 0.0, height, 0, 1); glOrtho (0.0, width, 0.0, height, 0, 1);
#endif #endif
@@ -64,10 +64,10 @@ void OpenGLHelpers::setPerspective (double fovy, double aspect, double zNear, do
glLoadIdentity(); glLoadIdentity();
#if JUCE_OPENGL_ES #if JUCE_OPENGL_ES
const float ymax = (float) (zNear * tan (fovy * double_Pi / 360.0));
const float ymin = -ymax;
const GLfloat ymax = (GLfloat) (zNear * tan (fovy * double_Pi / 360.0));
const GLfloat ymin = -ymax;
glFrustumf (ymin * (float) aspect, ymax * (float) aspect, ymin, ymax, (float) zNear, (float) zFar);
glFrustumf (ymin * (GLfloat) aspect, ymax * (GLfloat) aspect, ymin, ymax, (GLfloat) zNear, (GLfloat) zFar);
#else #else
const double ymax = zNear * tan (fovy * double_Pi / 360.0); const double ymax = zNear * tan (fovy * double_Pi / 360.0);
const double ymin = -ymax; const double ymin = -ymax;
@@ -136,7 +136,6 @@ namespace OpenGLGradientHelpers
{ {
void drawTriangles (GLenum mode, const GLfloat* vertices, const GLfloat* textureCoords, const int numElements) void drawTriangles (GLenum mode, const GLfloat* vertices, const GLfloat* textureCoords, const int numElements)
{ {
glEnable (GL_BLEND);
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY);
@@ -164,10 +163,10 @@ namespace OpenGLGradientHelpers
p2.getX(), p2.getY(), 1.0f, 0.0f, p2.getX(), p2.getY(), 1.0f, 0.0f,
p3.getX(), p3.getY(), 0.0f, 1.0f)); p3.getX(), p3.getY(), 0.0f, 1.0f));
const float l = (float) rect.getX();
const float r = (float) rect.getRight();
const float t = (float) rect.getY();
const float b = (float) rect.getBottom();
const GLfloat l = (GLfloat) rect.getX();
const GLfloat r = (GLfloat) rect.getRight();
const GLfloat t = (GLfloat) rect.getY();
const GLfloat b = (GLfloat) rect.getBottom();
const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; const GLfloat vertices[] = { l, t, r, t, l, b, r, b };
GLfloat textureCoords[] = { l, t, r, t, l, b, r, b }; GLfloat textureCoords[] = { l, t, r, t, l, b, r, b };
@@ -202,8 +201,7 @@ namespace OpenGLGradientHelpers
*t++ = 0.0f; *t++ = 0.0f;
*t++ = 0.0f; *t++ = 0.0f;
const float originalRadius = grad.point1.getDistanceFrom (grad.point2);
const float texturePos = sourceRadius / originalRadius;
const GLfloat texturePos = sourceRadius / grad.point1.getDistanceFrom (grad.point2);
for (int i = numDivisions + 1; --i >= 0;) for (int i = numDivisions + 1; --i >= 0;)
{ {
@@ -280,15 +278,54 @@ void OpenGLHelpers::fillRectWithColour (const Rectangle<int>& rect, const Colour
void OpenGLHelpers::fillRect (const Rectangle<int>& rect) void OpenGLHelpers::fillRect (const Rectangle<int>& rect)
{ {
const GLfloat vertices[] = { (float) rect.getX(), (float) rect.getY(),
(float) rect.getRight(), (float) rect.getY(),
(float) rect.getX(), (float) rect.getBottom(),
(float) rect.getRight(), (float) rect.getBottom() };
const GLfloat vertices[] = { (GLfloat) rect.getX(), (GLfloat) rect.getY(),
(GLfloat) rect.getRight(), (GLfloat) rect.getY(),
(GLfloat) rect.getX(), (GLfloat) rect.getBottom(),
(GLfloat) rect.getRight(), (GLfloat) rect.getBottom() };
glVertexPointer (2, GL_FLOAT, 0, vertices); glVertexPointer (2, GL_FLOAT, 0, vertices);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
} }
void OpenGLHelpers::fillRectWithTiledTexture (int textureWidth, int textureHeight,
const Rectangle<int>& clip,
const AffineTransform& transform,
float alpha)
{
glEnable (GL_TEXTURE_2D);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_NORMAL_ARRAY);
glColor4f (1.0f, 1.0f, 1.0f, alpha);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
const GLfloat clipX = (GLfloat) clip.getX();
const GLfloat clipY = (GLfloat) clip.getY();
const GLfloat clipR = (GLfloat) clip.getRight();
const GLfloat clipB = (GLfloat) clip.getBottom();
const GLfloat vertices[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB };
GLfloat textureCoords[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB };
{
const AffineTransform t (transform.inverted().scaled (1.0f / textureWidth,
1.0f / textureHeight));
t.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]);
t.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]);
}
glVertexPointer (2, GL_FLOAT, 0, vertices);
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
}
//============================================================================== //==============================================================================
// This breaks down a path into a series of horizontal strips of trapezoids.. // This breaks down a path into a series of horizontal strips of trapezoids..
class TriangulatedPath::TrapezoidedPath class TriangulatedPath::TrapezoidedPath
@@ -575,6 +612,8 @@ TriangulatedPath::TriangulatedPath (const Path& path, const AffineTransform& tra
TrapezoidedPath (path, transform).iterate (*this); TrapezoidedPath (path, transform).iterate (*this);
} }
TriangulatedPath::~TriangulatedPath() {}
void TriangulatedPath::draw (const int oversamplingLevel) const void TriangulatedPath::draw (const int oversamplingLevel) const
{ {
glColor4f (1.0f, 1.0f, 1.0f, 1.0f / (oversamplingLevel * oversamplingLevel)); glColor4f (1.0f, 1.0f, 1.0f, 1.0f / (oversamplingLevel * oversamplingLevel));
@@ -670,214 +709,5 @@ void OpenGLRenderingTarget::prepareFor2D()
getRenderingTargetHeight()); getRenderingTargetHeight());
} }
namespace GLPathRendering
{
void clipToPath (OpenGLRenderingTarget& target,
const Path& path, const AffineTransform& transform)
{
const int w = target.getRenderingTargetWidth();
const int h = target.getRenderingTargetHeight();
OpenGLFrameBuffer fb;
fb.initialise (w, h);
fb.makeCurrentAndClear();
fb.createAlphaChannelFromPath (path, transform);
target.makeCurrentRenderingTarget();
target.prepareFor2D();
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glBlendFunc (GL_DST_ALPHA, GL_ZERO);
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
fb.drawAt (0, 0);
}
void fillPathWithColour (OpenGLRenderingTarget& target,
const Rectangle<int>& clip, const Path& path,
const AffineTransform& pathTransform,
const Colour& colour)
{
OpenGLFrameBuffer f;
f.initialise (clip.getWidth(), clip.getHeight());
f.makeCurrentAndClear();
f.createAlphaChannelFromPath (path, pathTransform.translated ((float) -clip.getX(), (float) -clip.getY())
.followedBy (AffineTransform::verticalFlip ((float) clip.getHeight())));
f.releaseAsRenderingTarget();
target.makeCurrentRenderingTarget();
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
OpenGLHelpers::setColour (colour);
target.prepareFor2D();
f.drawAt ((float) clip.getX(), (float) (target.getRenderingTargetHeight() - clip.getBottom()));
}
void fillPathWithGradient (OpenGLRenderingTarget& target,
const Rectangle<int>& clip, const Path& path,
const AffineTransform& pathTransform,
const ColourGradient& grad,
const AffineTransform& gradientTransform,
const GLfloat alpha)
{
const int targetHeight = target.getRenderingTargetHeight();
OpenGLFrameBuffer f;
f.initialise (clip.getWidth(), clip.getHeight());
f.makeCurrentAndClear();
const AffineTransform correction (AffineTransform::translation ((float) -clip.getX(), (float) -clip.getY())
.followedBy (AffineTransform::verticalFlip ((float) clip.getHeight())));
f.createAlphaChannelFromPath (path, pathTransform.followedBy (correction));
f.makeCurrentRenderingTarget();
f.prepareFor2D();
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc (GL_DST_ALPHA, GL_ZERO);
OpenGLHelpers::fillRectWithColourGradient (Rectangle<int> (0, 0, clip.getWidth(), clip.getHeight()),
grad, gradientTransform.followedBy (correction));
f.releaseAsRenderingTarget();
target.makeCurrentRenderingTarget();
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f (alpha, alpha, alpha, alpha);
target.prepareFor2D();
f.drawAt ((float) clip.getX(), (float) (targetHeight - clip.getBottom()));
}
void fillPathWithImage (OpenGLRenderingTarget& target,
const Rectangle<int>& clip, const Path& path,
const AffineTransform& transform,
GLuint textureID, GLfloat textureWidth, GLfloat textureHeight,
const AffineTransform& textureTransform,
const bool tiled,
const GLfloat alpha)
{
const int targetHeight = target.getRenderingTargetHeight();
OpenGLFrameBuffer f;
f.initialise (clip.getWidth(), clip.getHeight());
f.makeCurrentRenderingTarget();
f.prepareFor2D();
glDisable (GL_BLEND);
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
const GLfloat clipX = (GLfloat) clip.getX();
const GLfloat clipY = (GLfloat) clip.getY();
const GLfloat clipH = (GLfloat) clip.getHeight();
const GLfloat clipB = (GLfloat) clip.getBottom();
const AffineTransform correction (AffineTransform::translation (-clipX, -clipY)
.followedBy (AffineTransform::verticalFlip (clipH)));
glBindTexture (GL_TEXTURE_2D, textureID);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_NORMAL_ARRAY);
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
if (tiled)
{
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
const GLfloat clipW = (GLfloat) clip.getWidth();
const GLfloat clipR = (GLfloat) clip.getRight();
const GLfloat vertices[] = { 0, clipH, clipW, clipH, 0, 0, clipW, 0 };
GLfloat textureCoords[] = { clipX, clipY, clipR, clipY, clipX, clipB, clipR, clipB };
{
const AffineTransform t (textureTransform.inverted().scaled (1.0f / textureWidth,
1.0f / textureHeight));
t.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]);
t.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]);
}
glVertexPointer (2, GL_FLOAT, 0, vertices);
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
}
else
{
glClearColor (0, 0, 0, 0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLfloat vertices[] = { 0, 0, textureWidth, 0, 0, textureHeight, textureWidth, textureHeight };
const GLfloat textureCoords[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f };
{
const AffineTransform t (textureTransform.followedBy (correction));
t.transformPoints (vertices[0], vertices[1], vertices[2], vertices[3]);
t.transformPoints (vertices[4], vertices[5], vertices[6], vertices[7]);
}
glVertexPointer (2, GL_FLOAT, 0, vertices);
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
}
glBindTexture (GL_TEXTURE_2D, 0);
clipToPath (f, path, transform.followedBy (correction));
f.releaseAsRenderingTarget();
target.makeCurrentRenderingTarget();
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f (1.0f, 1.0f, 1.0f, alpha);
target.prepareFor2D();
f.drawAt (clipX, targetHeight - clipB);
}
}
void OpenGLRenderingTarget::fillPath (const Rectangle<int>& clip,
const Path& path, const AffineTransform& transform,
const FillType& fill)
{
if (! fill.isInvisible())
{
if (fill.isColour())
{
GLPathRendering::fillPathWithColour (*this, clip, path, transform, fill.colour);
}
else if (fill.isGradient())
{
GLPathRendering::fillPathWithGradient (*this, clip, path, transform,
*(fill.gradient), fill.transform,
fill.colour.getFloatAlpha());
}
else if (fill.isTiledImage())
{
OpenGLTextureFromImage t (fill.image);
GLPathRendering::fillPathWithImage (*this, clip, path, transform,
t.textureID, (GLfloat) t.width, (GLfloat) t.height,
fill.transform, true,
fill.colour.getFloatAlpha());
}
}
}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 12
- 1
modules/juce_opengl/opengl/juce_OpenGLHelpers.h View File

@@ -40,6 +40,9 @@ public:
/** Clears the GL error state. */ /** Clears the GL error state. */
static void resetErrorState(); static void resetErrorState();
/** Returns true if the current thread has an active OpenGL context. */
static bool isContextActive();
/** Clears the current context using the given colour. */ /** Clears the current context using the given colour. */
static void clear (const Colour& colour); static void clear (const Colour& colour);
@@ -78,6 +81,11 @@ public:
static void fillRectWithColourGradient (const Rectangle<int>& rect, static void fillRectWithColourGradient (const Rectangle<int>& rect,
const ColourGradient& gradient, const ColourGradient& gradient,
const AffineTransform& transform); const AffineTransform& transform);
static void fillRectWithTiledTexture (int textureWidth, int textureHeight,
const Rectangle<int>& targetArea,
const AffineTransform& transform,
float alpha);
}; };
//============================================================================== //==============================================================================
@@ -88,6 +96,9 @@ class JUCE_API TriangulatedPath
public: public:
TriangulatedPath (const Path& path, const AffineTransform& transform); TriangulatedPath (const Path& path, const AffineTransform& transform);
/** Destructor. */
~TriangulatedPath();
/** Renders the path, using a jittered oversampling method. /** Renders the path, using a jittered oversampling method.
The oversampling level is the square root of the number of times it The oversampling level is the square root of the number of times it
should be oversampled, so 3 or 4 might be reasonable. should be oversampled, so 3 or 4 might be reasonable.
@@ -102,7 +113,7 @@ private:
friend class TrapezoidedPath; friend class TrapezoidedPath;
void startNewBlock(); void startNewBlock();
void addTriangle (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3);
void addTriangle (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3);
void addTrapezoid (GLfloat y1, GLfloat y2, GLfloat x1, GLfloat x2, GLfloat x3, GLfloat x4); void addTrapezoid (GLfloat y1, GLfloat y2, GLfloat x1, GLfloat x2, GLfloat x3, GLfloat x4);
struct TriangleBlock; struct TriangleBlock;


+ 0
- 5
modules/juce_opengl/opengl/juce_OpenGLRenderingTarget.h View File

@@ -51,11 +51,6 @@ public:
@see OpenGLHelpers::prepareFor2D @see OpenGLHelpers::prepareFor2D
*/ */
void prepareFor2D(); void prepareFor2D();
/** Fills a path with a custom FillType. */
void fillPath (const Rectangle<int>& clipArea,
const Path& path, const AffineTransform& pathTransform,
const FillType& fill);
}; };


+ 4
- 0
modules/juce_opengl/opengl/juce_OpenGLTexture.cpp View File

@@ -49,6 +49,10 @@ bool OpenGLTexture::isValidSize (int width, int height)
void OpenGLTexture::create (const int w, const int h) void OpenGLTexture::create (const int w, const int h)
{ {
// Texture objects can only be created when the current thread has an active OpenGL
// context. You'll need to make an OpenGLComponent active before calling this.
jassert (OpenGLHelpers::isContextActive());
jassert (isValidSize (w, h)); // Perhaps these dimensions must be a power-of-two? jassert (isValidSize (w, h)); // Perhaps these dimensions must be a power-of-two?
release(); release();


Loading…
Cancel
Save