mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-03 03:30:06 +00:00
More OpenGL work.
This commit is contained in:
parent
74a727b42f
commit
0422e4ced9
9 changed files with 195 additions and 145 deletions
|
|
@ -51,8 +51,6 @@ END_JUCE_NAMESPACE
|
|||
- (BOOL) resignFirstResponder;
|
||||
- (BOOL) canBecomeFirstResponder;
|
||||
|
||||
- (void) asyncRepaint: (id) rect;
|
||||
|
||||
- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text;
|
||||
@end
|
||||
|
||||
|
|
@ -343,12 +341,6 @@ juce::Point<int> juce_lastMousePos;
|
|||
return owner != nullptr && owner->canBecomeKeyWindow();
|
||||
}
|
||||
|
||||
- (void) asyncRepaint: (id) rect
|
||||
{
|
||||
CGRect* r = (CGRect*) [((NSData*) rect) bytes];
|
||||
[self setNeedsDisplayInRect: *r];
|
||||
}
|
||||
|
||||
- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
|
||||
{
|
||||
return owner->textViewReplaceCharacters (Range<int> (range.location, range.location + range.length),
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ END_JUCE_NAMESPACE
|
|||
{
|
||||
const ScopedLock sl (*contextLock);
|
||||
|
||||
if ([self openGLContext] == 0)
|
||||
if ([self openGLContext] == nil)
|
||||
return false;
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
|
|
@ -108,15 +108,8 @@ END_JUCE_NAMESPACE
|
|||
needsUpdate = true;
|
||||
}
|
||||
|
||||
- (void) rightMouseDown: (NSEvent*) ev
|
||||
{
|
||||
[[self superview] rightMouseDown: ev];
|
||||
}
|
||||
|
||||
- (void) rightMouseUp: (NSEvent*) ev
|
||||
{
|
||||
[[self superview] rightMouseUp: ev];
|
||||
}
|
||||
- (void) rightMouseDown: (NSEvent*) ev { [[self superview] rightMouseDown: ev]; }
|
||||
- (void) rightMouseUp: (NSEvent*) ev { [[self superview] rightMouseUp: ev]; }
|
||||
|
||||
@end
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
|
@ -275,5 +268,5 @@ void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>&)
|
|||
//==============================================================================
|
||||
bool OpenGLHelpers::isContextActive()
|
||||
{
|
||||
return [NSOpenGLContext currentContext] != nil;
|
||||
return CGLGetCurrentContext() != 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public:
|
|||
depthOrStencilBuffer (0),
|
||||
hasDepthBuffer (false),
|
||||
hasStencilBuffer (false),
|
||||
ok (false)
|
||||
ok (true)
|
||||
{
|
||||
// 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.
|
||||
|
|
@ -180,8 +180,6 @@ public:
|
|||
hasStencilBuffer = wantsStencilBuffer;
|
||||
}
|
||||
|
||||
ok = checkStatus();
|
||||
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
|
|
@ -197,25 +195,14 @@ public:
|
|||
glDeleteFramebuffersEXT (1, &frameBufferHandle);
|
||||
}
|
||||
|
||||
bool bind() { return bind (frameBufferHandle); }
|
||||
bool unbind() { return bind (0); }
|
||||
void bind() { glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferHandle); }
|
||||
void unbind() { glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); }
|
||||
|
||||
const int width, height;
|
||||
GLuint textureID, frameBufferHandle, depthOrStencilBuffer;
|
||||
bool hasDepthBuffer, hasStencilBuffer, ok;
|
||||
|
||||
private:
|
||||
bool bind (GLuint buffer)
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, buffer);
|
||||
ok = checkStatus();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool checkStatus() noexcept
|
||||
{
|
||||
const GLenum status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
|
||||
|
|
@ -347,7 +334,11 @@ bool OpenGLFrameBuffer::makeCurrentRenderingTarget()
|
|||
// reloadSavedCopy() to put it back into GPU memory before using it..
|
||||
jassert (savedState == nullptr);
|
||||
|
||||
return pimpl != nullptr && pimpl->bind();
|
||||
if (pimpl == nullptr)
|
||||
return false;
|
||||
|
||||
pimpl->bind();
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::setCurrentFrameBufferTarget (GLuint frameBufferID)
|
||||
|
|
@ -355,6 +346,13 @@ void OpenGLFrameBuffer::setCurrentFrameBufferTarget (GLuint frameBufferID)
|
|||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferID);
|
||||
}
|
||||
|
||||
GLuint OpenGLFrameBuffer::getCurrentFrameBufferTarget()
|
||||
{
|
||||
GLint fb;
|
||||
glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fb);
|
||||
return (GLuint) fb;
|
||||
}
|
||||
|
||||
void OpenGLFrameBuffer::releaseAsRenderingTarget()
|
||||
{
|
||||
setCurrentFrameBufferTarget (0);
|
||||
|
|
@ -397,16 +395,16 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>
|
|||
OpenGLHelpers::prepareFor2D (pimpl->width, pimpl->height);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_BLEND);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
#if JUCE_OPENGL_ES
|
||||
{
|
||||
// GLES has no glDrawPixels function, so we have to create a texture and draw it..
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
OpenGLTexture temp;
|
||||
temp.load (data, area.getWidth(), area.getHeight());
|
||||
temp.bind();
|
||||
OpenGLTexture tex;
|
||||
tex.load (data, area.getWidth(), area.getHeight());
|
||||
tex.bind();
|
||||
|
||||
const GLint cropRect[4] = { 0, 0, area.getWidth(), area.getHeight() };
|
||||
glTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
||||
|
|
@ -415,10 +413,12 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>
|
|||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
}
|
||||
#else
|
||||
glRasterPos2i (area.getX(), area.getY());
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
glDrawPixels (area.getWidth(), area.getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
|
||||
{
|
||||
OpenGLTexture tex;
|
||||
tex.load (data, area.getWidth(), area.getHeight());
|
||||
|
||||
OpenGLHelpers::fillRectWithTexture (area.withSize (tex.getWidth(), tex.getHeight()), tex.getTextureID(), 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ public:
|
|||
*/
|
||||
static void setCurrentFrameBufferTarget (GLuint frameBufferID);
|
||||
|
||||
/** Returns the ID of the currently-bound framebuffer. */
|
||||
static GLuint getCurrentFrameBufferTarget();
|
||||
|
||||
/** Clears the framebuffer with the specified colour. */
|
||||
void clear (const Colour& colour);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,67 +103,14 @@ namespace
|
|||
glColor4f (alpha, alpha, alpha, alpha);
|
||||
}
|
||||
|
||||
void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept
|
||||
{
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glDisableClientState (GL_COLOR_ARRAY);
|
||||
glDisableClientState (GL_NORMAL_ARRAY);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glVertexPointer (2, GL_FLOAT, 0, vertices);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, numVertices);
|
||||
}
|
||||
|
||||
void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords,
|
||||
const int numVertices, const GLuint textureID) noexcept
|
||||
{
|
||||
jassert (textureID != 0);
|
||||
glBindTexture (GL_TEXTURE_2D, textureID);
|
||||
drawTriangleStrip (vertices, textureCoords, numVertices);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void drawTextureQuad (GLuint textureID, int x, int y, int w, int h)
|
||||
{
|
||||
const GLfloat l = (GLfloat) x;
|
||||
const GLfloat t = (GLfloat) y;
|
||||
const GLfloat r = (GLfloat) (x + w);
|
||||
const GLfloat b = (GLfloat) (y + h);
|
||||
|
||||
const GLfloat vertices[] = { l, t, r, t, l, b, r, b };
|
||||
const GLfloat textureCoords[] = { 0, 1.0f, 1.0f, 1.0f, 0, 0, 1.0f, 0 };
|
||||
|
||||
drawTriangleStrip (vertices, textureCoords, 4, textureID);
|
||||
}
|
||||
|
||||
void fillRectWithTexture (const Rectangle<int>& rect, GLuint textureID, const float alpha)
|
||||
{
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glColor4f (1.0f, 1.0f, 1.0f, alpha);
|
||||
|
||||
drawTextureQuad (textureID, rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
|
||||
}
|
||||
|
||||
void clipFrameBuffers (const OpenGLTarget& dest, OpenGLFrameBuffer& source,
|
||||
const Point<int> sourceOrigin, const bool shouldMaskRGB)
|
||||
void clipFrameBuffers (const OpenGLTarget& dest, OpenGLFrameBuffer& source, const Point<int> sourceOrigin)
|
||||
{
|
||||
dest.makeActiveFor2D();
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_ZERO, GL_SRC_ALPHA);
|
||||
setColour (1.0f);
|
||||
|
||||
if (shouldMaskRGB)
|
||||
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
|
||||
drawTextureQuad (source.getTextureID(), sourceOrigin.getX(), sourceOrigin.getY(),
|
||||
source.getWidth(), source.getHeight());
|
||||
|
||||
if (shouldMaskRGB)
|
||||
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
OpenGLHelpers::drawTextureQuad (source.getTextureID(), sourceOrigin.getX(), sourceOrigin.getY(),
|
||||
source.getWidth(), source.getHeight());
|
||||
}
|
||||
|
||||
void renderPath (const Path& path, const AffineTransform& transform, int oversamplingLevel)
|
||||
|
|
@ -177,10 +124,10 @@ namespace
|
|||
TriangulatedPath (path, transform).draw (oversamplingLevel);
|
||||
}
|
||||
|
||||
void setNormalBlendingMode() noexcept
|
||||
void setPremultipliedBlendingMode() noexcept
|
||||
{
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void setBlendMode (const bool replaceExistingContents) noexcept
|
||||
|
|
@ -188,7 +135,7 @@ namespace
|
|||
if (replaceExistingContents)
|
||||
glDisable (GL_BLEND);
|
||||
else
|
||||
setNormalBlendingMode();
|
||||
setPremultipliedBlendingMode();
|
||||
}
|
||||
|
||||
void fillRectWithTiledTexture (const OpenGLTarget& target, int textureWidth, int textureHeight,
|
||||
|
|
@ -295,7 +242,8 @@ namespace
|
|||
textureTransform.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]);
|
||||
textureTransform.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]);
|
||||
|
||||
drawTriangleStrip (vertices, textureCoords, 4);
|
||||
setColour (1.0f);
|
||||
OpenGLHelpers::drawTriangleStrip (vertices, textureCoords, 4);
|
||||
}
|
||||
|
||||
void fillWithRadialGradient (const OpenGLTarget& target, const Rectangle<int>& rect,
|
||||
|
|
@ -442,7 +390,6 @@ public:
|
|||
virtual Ptr clipToEdgeTable (const EdgeTable&) = 0;
|
||||
virtual Ptr clipToImageAlpha (const OpenGLTextureFromImage&, const AffineTransform&) = 0;
|
||||
virtual Ptr clipToMask (ClipRegion_Mask*) = 0;
|
||||
virtual void translate (const Point<int>& delta) = 0;
|
||||
virtual const Rectangle<int>& getClipBounds() const = 0;
|
||||
virtual void fillAll (const OpenGLTarget&, const FillType& fill, bool replaceContents) = 0;
|
||||
virtual void fillRect (const OpenGLTarget&, const Rectangle<int>& area, const FillType& fill, bool replaceContents) = 0;
|
||||
|
|
@ -489,7 +436,7 @@ public:
|
|||
maskOrigin (clip.getPosition())
|
||||
{
|
||||
initialiseClear();
|
||||
OpenGLHelpers::fillEdgeTable (e, 0, 0, 0);
|
||||
OpenGLHelpers::fillEdgeTable (e);
|
||||
}
|
||||
|
||||
ClipRegion_Mask (const Rectangle<int>& bounds, const Path& p, const AffineTransform& transform, int oversamplingLevel)
|
||||
|
|
@ -511,12 +458,6 @@ public:
|
|||
const Rectangle<int>& getClipBounds() const { return clip; }
|
||||
Ptr applyClipTo (const Ptr& target) { return target->clipToMask (this); }
|
||||
|
||||
void translate (const Point<int>& delta)
|
||||
{
|
||||
maskOrigin += delta;
|
||||
clip += delta;
|
||||
}
|
||||
|
||||
Ptr clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
clip = clip.getIntersection (r);
|
||||
|
|
@ -579,7 +520,7 @@ public:
|
|||
if (clip.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
clipFrameBuffers (OpenGLTarget (mask, maskOrigin), m->mask, m->maskOrigin, true);
|
||||
clipFrameBuffers (OpenGLTarget (mask, maskOrigin), m->mask, m->maskOrigin);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +586,7 @@ public:
|
|||
OpenGLTarget bufferTarget (buffer, bufferArea.getPosition());
|
||||
bufferTarget.makeActiveFor2D();
|
||||
glDisable (GL_BLEND);
|
||||
fillRectWithTexture (targetArea, source.textureID, alpha);
|
||||
OpenGLHelpers::fillRectWithTexture (targetArea, source.textureID, alpha);
|
||||
|
||||
clipAndDraw (target, bufferTarget);
|
||||
}
|
||||
|
|
@ -703,7 +644,7 @@ private:
|
|||
const GLfloat b = (GLfloat) (y + h);
|
||||
|
||||
const GLfloat vertices[] = { l, t, r, t, l, b, r, b };
|
||||
glColor4f (1.0f, 1.0f, 1.0f, alpha / 255.0f);
|
||||
setColour (alpha / 255.0f);
|
||||
glVertexPointer (2, GL_FLOAT, 0, vertices);
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
|
@ -711,7 +652,7 @@ private:
|
|||
|
||||
void clipAndDraw (const OpenGLTarget& target, const OpenGLTarget& buffer)
|
||||
{
|
||||
clipFrameBuffers (buffer, mask, maskOrigin, false);
|
||||
clipFrameBuffers (buffer, mask, maskOrigin);
|
||||
|
||||
target.makeActiveFor2D();
|
||||
glEnable (GL_BLEND);
|
||||
|
|
@ -723,8 +664,8 @@ private:
|
|||
|
||||
void drawFrameBuffer (const OpenGLFrameBuffer& buffer, const Point<int>& topLeft)
|
||||
{
|
||||
drawTextureQuad (buffer.getTextureID(), topLeft.getX(), topLeft.getY(),
|
||||
buffer.getWidth(), buffer.getHeight());
|
||||
OpenGLHelpers::drawTextureQuad (buffer.getTextureID(), topLeft.getX(), topLeft.getY(),
|
||||
buffer.getWidth(), buffer.getHeight());
|
||||
}
|
||||
|
||||
void fillMaskWithSourceImage (const OpenGLTextureFromImage& image, const AffineTransform& transform) const
|
||||
|
|
@ -749,7 +690,12 @@ private:
|
|||
inv.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]);
|
||||
inv.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]);
|
||||
|
||||
drawTriangleStrip (vertices, textureCoords, 4);
|
||||
textureCoords[1] = 1.0f - textureCoords[1];
|
||||
textureCoords[3] = 1.0f - textureCoords[3];
|
||||
textureCoords[5] = 1.0f - textureCoords[5];
|
||||
textureCoords[7] = 1.0f - textureCoords[7];
|
||||
|
||||
OpenGLHelpers::drawTriangleStrip (vertices, textureCoords, 4);
|
||||
}
|
||||
|
||||
ClipRegion_Mask& operator= (const ClipRegion_Mask&);
|
||||
|
|
@ -767,7 +713,6 @@ public:
|
|||
Ptr clone() const { return new ClipRegion_Rectangle (clip); }
|
||||
const Rectangle<int>& getClipBounds() const { return clip; }
|
||||
Ptr applyClipTo (const Ptr& target) { return target->clipToRectangle (clip); }
|
||||
void translate (const Point<int>& delta) { clip += delta; }
|
||||
|
||||
Ptr clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
|
|
@ -814,8 +759,8 @@ public:
|
|||
{
|
||||
target.makeActiveFor2D();
|
||||
target.scissor (clip);
|
||||
setNormalBlendingMode();
|
||||
fillRectWithTexture (targetArea, source.textureID, alpha);
|
||||
setPremultipliedBlendingMode();
|
||||
OpenGLHelpers::fillRectWithTexture (targetArea, source.textureID, alpha);
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
|
|
@ -977,12 +922,11 @@ public:
|
|||
|
||||
OpenGLFrameBufferImage* fbi = new OpenGLFrameBufferImage (clipBounds.getWidth(), clipBounds.getHeight());
|
||||
fbi->frameBuffer.clear (Colours::transparentBlack);
|
||||
|
||||
s->transparencyLayer = Image (fbi);
|
||||
s->target = OpenGLTarget (fbi->frameBuffer, Point<int>());
|
||||
s->target = OpenGLTarget (fbi->frameBuffer, clipBounds.getPosition());
|
||||
s->transparencyLayerAlpha = opacity;
|
||||
s->transform.moveOriginInDeviceSpace (-clipBounds.getX(), -clipBounds.getY());
|
||||
s->cloneClipIfMultiplyReferenced();
|
||||
s->clip->translate (-clipBounds.getPosition());
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
@ -1048,17 +992,34 @@ public:
|
|||
{
|
||||
if (clip != nullptr)
|
||||
{
|
||||
const float fontHeight = font.getHeight();
|
||||
if (transform.isOnlyTranslated && t.isOnlyTranslation())
|
||||
{
|
||||
RenderingHelpers::GlyphCache <CachedGlyphEdgeTable, SavedState>::getInstance()
|
||||
.drawGlyph (*this, font, glyphNumber,
|
||||
transform.xOffset + t.getTranslationX(),
|
||||
transform.yOffset + t.getTranslationY());
|
||||
}
|
||||
else
|
||||
{
|
||||
const float fontHeight = font.getHeight();
|
||||
|
||||
const ScopedPointer<EdgeTable> et (font.getTypeface()->getEdgeTableForGlyph
|
||||
(glyphNumber, transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
.followedBy (t))));
|
||||
const ScopedPointer<EdgeTable> et (font.getTypeface()->getEdgeTableForGlyph
|
||||
(glyphNumber, transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
.followedBy (t))));
|
||||
|
||||
if (et != nullptr)
|
||||
fillShape (new ClipRegion_Mask (*et), false);
|
||||
if (et != nullptr)
|
||||
fillShape (new ClipRegion_Mask (*et), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillEdgeTable (const EdgeTable& et, float x, int y)
|
||||
{
|
||||
EdgeTable et2 (et);
|
||||
et2.translate (x, y);
|
||||
fillShape (new ClipRegion_Mask (et2), false);
|
||||
}
|
||||
|
||||
void drawLine (const Line <float>& line)
|
||||
{
|
||||
Path p;
|
||||
|
|
@ -1147,10 +1108,48 @@ private:
|
|||
return fillType.transformed (transform.getTransform());
|
||||
}
|
||||
|
||||
class CachedGlyphEdgeTable
|
||||
{
|
||||
public:
|
||||
CachedGlyphEdgeTable() : glyph (0), lastAccessCount (0) {}
|
||||
|
||||
void draw (OpenGLRenderer::SavedState& state, float x, const float y) const
|
||||
{
|
||||
if (snapToIntegerCoordinate)
|
||||
x = std::floor (x + 0.5f);
|
||||
|
||||
if (edgeTable != nullptr)
|
||||
state.fillEdgeTable (*edgeTable, x, roundToInt (y));
|
||||
}
|
||||
|
||||
void generate (const Font& newFont, const int glyphNumber)
|
||||
{
|
||||
font = newFont;
|
||||
snapToIntegerCoordinate = newFont.getTypeface()->isHinted();
|
||||
glyph = glyphNumber;
|
||||
|
||||
const float fontHeight = font.getHeight();
|
||||
edgeTable = font.getTypeface()->getEdgeTableForGlyph (glyphNumber,
|
||||
AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
.translated (0.0f, -0.5f)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
Font font;
|
||||
int glyph, lastAccessCount;
|
||||
bool snapToIntegerCoordinate;
|
||||
|
||||
private:
|
||||
ScopedPointer <EdgeTable> edgeTable;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable);
|
||||
};
|
||||
|
||||
SavedState& operator= (const SavedState&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
OpenGLRenderer::OpenGLRenderer (OpenGLComponent& target)
|
||||
: stack (new SavedState (OpenGLTarget (target.getFrameBufferID(), target.getWidth(), target.getHeight())))
|
||||
|
|
@ -1165,6 +1164,13 @@ OpenGLRenderer::OpenGLRenderer (OpenGLFrameBuffer& target)
|
|||
jassert (OpenGLHelpers::isContextActive());
|
||||
}
|
||||
|
||||
OpenGLRenderer::OpenGLRenderer (unsigned int frameBufferID, int width, int height)
|
||||
: stack (new SavedState (OpenGLTarget (frameBufferID, width, height)))
|
||||
{
|
||||
// This object can only be created and used when the current thread has an active OpenGL context.
|
||||
jassert (OpenGLHelpers::isContextActive());
|
||||
}
|
||||
|
||||
OpenGLRenderer::~OpenGLRenderer() {}
|
||||
|
||||
bool OpenGLRenderer::isVectorDevice() const { return false; }
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class JUCE_API OpenGLRenderer : public LowLevelGraphicsContext
|
|||
public:
|
||||
explicit OpenGLRenderer (OpenGLComponent& target);
|
||||
explicit OpenGLRenderer (OpenGLFrameBuffer& target);
|
||||
OpenGLRenderer (unsigned int frameBufferID, int width, int height);
|
||||
~OpenGLRenderer();
|
||||
|
||||
bool isVectorDevice() const;
|
||||
|
|
|
|||
|
|
@ -213,6 +213,51 @@ void OpenGLHelpers::drawQuad3D (float x1, float y1, float z1,
|
|||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
void OpenGLHelpers::drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept
|
||||
{
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glDisableClientState (GL_COLOR_ARRAY);
|
||||
glDisableClientState (GL_NORMAL_ARRAY);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glVertexPointer (2, GL_FLOAT, 0, vertices);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, numVertices);
|
||||
}
|
||||
|
||||
void OpenGLHelpers::drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords,
|
||||
const int numVertices, const GLuint textureID) noexcept
|
||||
{
|
||||
jassert (textureID != 0);
|
||||
glBindTexture (GL_TEXTURE_2D, textureID);
|
||||
drawTriangleStrip (vertices, textureCoords, numVertices);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void OpenGLHelpers::drawTextureQuad (GLuint textureID, int x, int y, int w, int h)
|
||||
{
|
||||
const GLfloat l = (GLfloat) x;
|
||||
const GLfloat t = (GLfloat) y;
|
||||
const GLfloat r = (GLfloat) (x + w);
|
||||
const GLfloat b = (GLfloat) (y + h);
|
||||
|
||||
const GLfloat vertices[] = { l, t, r, t, l, b, r, b };
|
||||
const GLfloat textureCoords[] = { 0, 1.0f, 1.0f, 1.0f, 0, 0, 1.0f, 0 };
|
||||
|
||||
drawTriangleStrip (vertices, textureCoords, 4, textureID);
|
||||
}
|
||||
|
||||
void OpenGLHelpers::fillRectWithTexture (const Rectangle<int>& rect, GLuint textureID, const float alpha)
|
||||
{
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glColor4f (alpha, alpha, alpha, alpha);
|
||||
|
||||
drawTextureQuad (textureID, rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void OpenGLHelpers::fillRectWithColour (const Rectangle<int>& rect, const Colour& colour)
|
||||
{
|
||||
|
|
@ -238,8 +283,8 @@ void OpenGLHelpers::fillRect (const Rectangle<int>& rect)
|
|||
//==============================================================================
|
||||
struct OpenGLEdgeTableRenderer
|
||||
{
|
||||
OpenGLEdgeTableRenderer (float r_, float g_, float b_) noexcept
|
||||
: r (r_), g (g_), b (b_), lastAlpha (-1)
|
||||
OpenGLEdgeTableRenderer() noexcept
|
||||
: lastAlpha (-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +325,6 @@ struct OpenGLEdgeTableRenderer
|
|||
|
||||
private:
|
||||
GLfloat vertices[8];
|
||||
const float r, g, b;
|
||||
int lastAlpha;
|
||||
|
||||
void drawHorizontal (int x, const int w, const int alphaLevel) noexcept
|
||||
|
|
@ -291,7 +335,8 @@ private:
|
|||
if (lastAlpha != alphaLevel)
|
||||
{
|
||||
lastAlpha = alphaLevel;
|
||||
glColor4f (r, g, b, alphaLevel / 255.0f);
|
||||
const float a = alphaLevel / 255.0f;
|
||||
glColor4f (a, a, a, a);
|
||||
}
|
||||
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
|
@ -300,10 +345,9 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE (OpenGLEdgeTableRenderer);
|
||||
};
|
||||
|
||||
void OpenGLHelpers::fillEdgeTable (const EdgeTable& edgeTable,
|
||||
float red, float green, float blue)
|
||||
void OpenGLHelpers::fillEdgeTable (const EdgeTable& edgeTable)
|
||||
{
|
||||
OpenGLEdgeTableRenderer etr (red, green, blue);
|
||||
OpenGLEdgeTableRenderer etr;
|
||||
etr.draw (edgeTable);
|
||||
}
|
||||
|
||||
|
|
@ -597,7 +641,8 @@ TriangulatedPath::~TriangulatedPath() {}
|
|||
|
||||
void TriangulatedPath::draw (const int oversamplingLevel) const
|
||||
{
|
||||
glColor4f (1.0f, 1.0f, 1.0f, 1.0f / (oversamplingLevel * oversamplingLevel));
|
||||
const float a = 1.0f / (oversamplingLevel * oversamplingLevel);
|
||||
glColor4f (a, a, a, a);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef (-0.5f, -0.5f, 0.0f);
|
||||
|
|
|
|||
|
|
@ -73,14 +73,23 @@ public:
|
|||
float x4, float y4, float z4,
|
||||
const Colour& colour);
|
||||
|
||||
static void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept;
|
||||
|
||||
static void drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords,
|
||||
const int numVertices, const GLuint textureID) noexcept;
|
||||
|
||||
static void drawTextureQuad (GLuint textureID, int x, int y, int w, int h);
|
||||
|
||||
static void fillRectWithTexture (const Rectangle<int>& rect, GLuint textureID, const float alpha);
|
||||
|
||||
static void fillRect (const Rectangle<int>& rect);
|
||||
|
||||
/** Fills a rectangle with the specified colour. */
|
||||
static void fillRectWithColour (const Rectangle<int>& rect,
|
||||
const Colour& colour);
|
||||
|
||||
/** Renders an edge-table into the current context. */
|
||||
static void fillEdgeTable (const EdgeTable& edgeTable,
|
||||
float red, float green, float blue);
|
||||
static void fillEdgeTable (const EdgeTable& edgeTable);
|
||||
|
||||
/** Checks whether the current context supports the specified extension. */
|
||||
static bool isExtensionSupported (const char* extensionName);
|
||||
|
|
|
|||
|
|
@ -94,13 +94,14 @@ void OpenGLTexture::load (const Image& image)
|
|||
const int srcLineStride = (srcData.pixelStride * imageW + 3) & ~3;
|
||||
dataCopy.malloc (textureW * textureH);
|
||||
data = dataCopy;
|
||||
const int yOffset = textureH - imageH;
|
||||
|
||||
if (srcData.pixelFormat == Image::RGB)
|
||||
{
|
||||
for (int y = 0; y < imageH; ++y)
|
||||
{
|
||||
const PixelRGB* const src = (const PixelRGB*) addBytesToPointer (srcData.data, srcLineStride * y);
|
||||
PixelARGB* const dst = (PixelARGB*) (dataCopy + textureW * y);
|
||||
PixelARGB* const dst = (PixelARGB*) (dataCopy + textureW * (y + yOffset));
|
||||
|
||||
for (int x = 0; x < imageW; ++x)
|
||||
dst[x].set (src[x]);
|
||||
|
|
@ -109,7 +110,7 @@ void OpenGLTexture::load (const Image& image)
|
|||
else if (srcData.pixelFormat == Image::ARGB)
|
||||
{
|
||||
for (int y = 0; y < imageH; ++y)
|
||||
memcpy (dataCopy + textureW * y, addBytesToPointer (srcData.data, srcLineStride * y), srcLineStride);
|
||||
memcpy (dataCopy + textureW * (y + yOffset), addBytesToPointer (srcData.data, srcLineStride * y), srcLineStride);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +129,7 @@ void OpenGLTexture::load (const PixelARGB* pixels, const int w, const int h)
|
|||
dataCopy.malloc (textureW * textureH);
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
memcpy (dataCopy + textureW * y, pixels + w * y, w * 4);
|
||||
memcpy (dataCopy + textureW * (y + textureH - h), pixels + w * y, w * 4);
|
||||
|
||||
pixels = dataCopy;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue