| @@ -842,6 +842,26 @@ namespace WavFileHelpers | |||
| return out.getMemoryBlock(); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| struct Clm_Chunk | |||
| { | |||
| static MemoryBlock createFrom (const StringPairArray& values) | |||
| { | |||
| MemoryOutputStream out; | |||
| auto s = values["clm "]; | |||
| if (s.isNotEmpty()) | |||
| { | |||
| out.writeString (s); | |||
| if ((out.getDataSize() & 1) != 0) | |||
| out.writeByte(0); | |||
| } | |||
| return out.getMemoryBlock(); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| namespace AXMLChunk | |||
| @@ -1321,6 +1341,7 @@ public: | |||
| listInfoChunk = ListInfoChunk::createFrom (metadataValues); | |||
| acidChunk = AcidChunk::createFrom (metadataValues); | |||
| trckChunk = TracktionChunk::createFrom (metadataValues); | |||
| clm_Chunk = Clm_Chunk::createFrom (metadataValues); | |||
| } | |||
| headerPosition = out->getPosition(); | |||
| @@ -1383,7 +1404,7 @@ public: | |||
| } | |||
| private: | |||
| MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk; | |||
| MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk, clm_Chunk; | |||
| uint64 lengthInSamples = 0, bytesWritten = 0; | |||
| int64 headerPosition = 0; | |||
| bool writeFailed = false; | |||
| @@ -1421,6 +1442,7 @@ private: | |||
| + chunkSize (listInfoChunk) | |||
| + chunkSize (acidChunk) | |||
| + chunkSize (trckChunk) | |||
| + chunkSize (clm_Chunk) | |||
| + (8 + 28)); // (ds64 chunk) | |||
| riffChunkSize += (riffChunkSize & 1); | |||
| @@ -1503,6 +1525,7 @@ private: | |||
| writeChunk (listInfoChunk, chunkName ("LIST")); | |||
| writeChunk (acidChunk, chunkName ("acid")); | |||
| writeChunk (trckChunk, chunkName ("Trkn")); | |||
| writeChunk (clm_Chunk, chunkName ("clm ")); | |||
| writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame)); | |||
| @@ -2625,6 +2625,9 @@ public: | |||
| //============================================================================== | |||
| void processParameterChanges (Vst::IParameterChanges& paramChanges) | |||
| { | |||
| if (juceVST3EditController == nullptr) | |||
| return; | |||
| jassert (pluginInstance != nullptr); | |||
| auto numParamsChanged = paramChanges.getParameterCount(); | |||
| @@ -408,6 +408,7 @@ public: | |||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||
| TRANS("Error when trying to open audio device!"), | |||
| error); | |||
| resized(); | |||
| } | |||
| bool showDeviceControlPanel() | |||
| @@ -1133,6 +1134,8 @@ void AudioDeviceSelectorComponent::updateMidiOutput() | |||
| deviceManager.setDefaultMidiOutputDevice ({}); | |||
| else | |||
| deviceManager.setDefaultMidiOutputDevice (currentMidiOutputs[selectedId - 1].identifier); | |||
| resized(); | |||
| } | |||
| void AudioDeviceSelectorComponent::changeListenerCallback (ChangeBroadcaster*) | |||
| @@ -338,6 +338,9 @@ public: | |||
| // or 3) data is in the in buffer | |||
| while ((! finished) && curlBuffer.getSize() == 0) | |||
| { | |||
| if (Thread::currentThreadShouldExit()) | |||
| return false; | |||
| { | |||
| const ScopedLock lock (cleanupLock); | |||
| @@ -74,6 +74,7 @@ struct SIMDNativeOps<float> | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE add (__m128 a, __m128 b) noexcept { return _mm_add_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE sub (__m128 a, __m128 b) noexcept { return _mm_sub_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE mul (__m128 a, __m128 b) noexcept { return _mm_mul_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE div (__m128 a, __m128 b) noexcept { return _mm_div_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE bit_and (__m128 a, __m128 b) noexcept { return _mm_and_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE bit_or (__m128 a, __m128 b) noexcept { return _mm_or_ps (a, b); } | |||
| static forcedinline __m128 JUCE_VECTOR_CALLTYPE bit_xor (__m128 a, __m128 b) noexcept { return _mm_xor_ps (a, b); } | |||
| @@ -142,6 +143,7 @@ struct SIMDNativeOps<double> | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE add (__m128d a, __m128d b) noexcept { return _mm_add_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE sub (__m128d a, __m128d b) noexcept { return _mm_sub_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE mul (__m128d a, __m128d b) noexcept { return _mm_mul_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE div (__m128d a, __m128d b) noexcept { return _mm_div_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE bit_and (__m128d a, __m128d b) noexcept { return _mm_and_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE bit_or (__m128d a, __m128d b) noexcept { return _mm_or_pd (a, b); } | |||
| static forcedinline __m128d JUCE_VECTOR_CALLTYPE bit_xor (__m128d a, __m128d b) noexcept { return _mm_xor_pd (a, b); } | |||
| @@ -369,6 +369,7 @@ void MessageManager::runDispatchLoop() | |||
| static void shutdownNSApp() | |||
| { | |||
| [NSApp stop: nil]; | |||
| [NSEvent stopPeriodicEvents]; | |||
| [NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: 0.1]; | |||
| } | |||
| @@ -482,10 +482,7 @@ void Button::mouseDrag (const MouseEvent& e) | |||
| bool Button::isMouseSourceOver (const MouseEvent& e) | |||
| { | |||
| if (e.source.isTouch() || e.source.isPen()) | |||
| return getLocalBounds().toFloat().contains (e.position); | |||
| return isMouseOver(); | |||
| return getLocalBounds().toFloat().contains (e.position); | |||
| } | |||
| void Button::focusGained (FocusChangeType) | |||
| @@ -76,9 +76,6 @@ void ShapeButton::setShape (const Path& newShape, | |||
| shape = newShape; | |||
| maintainShapeProportions = maintainShapeProportions_; | |||
| shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 3, Point<int>())); | |||
| setComponentEffect (hasShadow ? &shadow : nullptr); | |||
| if (resizeNowToFitThisShape) | |||
| { | |||
| auto newBounds = shape.getBounds(); | |||
| @@ -88,6 +88,8 @@ public: | |||
| Colour overColourOn, | |||
| Colour downColourOn); | |||
| void setShadowColour (Colour shadow) { shadowColour = shadow; } | |||
| /** Set whether the button should use the 'on' set of colours when its toggle state is 'on'. | |||
| By default these will be the same as the normal colours but the setOnColours method can be | |||
| used to provide a different set of colours. | |||
| @@ -112,9 +114,8 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| Colour normalColour, overColour, downColour, | |||
| normalColourOn, overColourOn, downColourOn, outlineColour; | |||
| normalColourOn, overColourOn, downColourOn, outlineColour, shadowColour; | |||
| bool useOnColours; | |||
| DropShadowEffect shadow; | |||
| Path shape; | |||
| BorderSize<int> border; | |||
| bool maintainShapeProportions; | |||
| @@ -387,6 +387,10 @@ struct Component::ComponentHelpers | |||
| template <typename PointOrRect> | |||
| static PointOrRect convertCoordinate (const Component* target, const Component* source, PointOrRect p) | |||
| { | |||
| float total_scaling = source->getTotalPixelScaling(); | |||
| Component* top = nullptr; | |||
| if (source) | |||
| top = source->getTopLevelComponent(); | |||
| while (source != nullptr) | |||
| { | |||
| if (source == target) | |||
| @@ -395,6 +399,9 @@ struct Component::ComponentHelpers | |||
| if (source->isParentOf (target)) | |||
| return convertFromDistantParentSpace (source, *target, p); | |||
| if (source == top) | |||
| p /= total_scaling; | |||
| p = convertToParentSpace (*source, p); | |||
| source = source->getParentComponent(); | |||
| } | |||
| @@ -1390,13 +1397,14 @@ bool Component::reallyContains (Point<int> point, bool returnTrueIfWithinAChild) | |||
| Component* Component::getComponentAt (Point<int> position) | |||
| { | |||
| Point<int> scale = (position.toFloat() * getPixelScaling()).roundToInt(); | |||
| if (flags.visibleFlag && ComponentHelpers::hitTest (*this, position)) | |||
| { | |||
| for (int i = childComponentList.size(); --i >= 0;) | |||
| { | |||
| auto* child = childComponentList.getUnchecked(i); | |||
| child = child->getComponentAt (ComponentHelpers::convertFromParentSpace (*child, position)); | |||
| child = child->getComponentAt (ComponentHelpers::convertFromParentSpace (*child, scale)); | |||
| if (child != nullptr) | |||
| return child; | |||
| @@ -3013,7 +3021,8 @@ void Component::modifierKeysChanged (const ModifierKeys& modifiers) | |||
| void Component::internalModifierKeysChanged() | |||
| { | |||
| sendFakeMouseMove(); | |||
| auto mainMouse = Desktop::getInstance().getMainMouseSource(); | |||
| mainMouse.triggerFakeMove(); | |||
| modifierKeysChanged (ModifierKeys::currentModifiers); | |||
| } | |||
| @@ -439,7 +439,7 @@ public: | |||
| @see setBounds, ComponentListener::componentMovedOrResized | |||
| */ | |||
| void setTopLeftPosition (Point<int> newTopLeftPosition); | |||
| virtual void setTopLeftPosition (Point<int> newTopLeftPosition); | |||
| /** Moves the component to a new position. | |||
| @@ -2281,6 +2281,17 @@ public: | |||
| */ | |||
| bool getViewportIgnoreDragFlag() const noexcept { return flags.viewportIgnoreDragFlag; } | |||
| virtual float getPixelScaling() const { return 1.0f; } | |||
| float getTotalPixelScaling() const { | |||
| const Component* component = this; | |||
| float pixel_scaling = 1.0f; | |||
| while (component) { | |||
| pixel_scaling *= component->getPixelScaling(); | |||
| component = component->getParentComponent(); | |||
| } | |||
| return pixel_scaling; | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| friend class ComponentPeer; | |||
| @@ -43,14 +43,9 @@ void CaretComponent::paint (Graphics& g) | |||
| g.fillRect (getLocalBounds()); | |||
| } | |||
| void CaretComponent::timerCallback() | |||
| { | |||
| setVisible (shouldBeShown() && ! isVisible()); | |||
| } | |||
| void CaretComponent::setCaretPosition (const Rectangle<int>& characterArea) | |||
| { | |||
| startTimer (380); | |||
| setVisible (shouldBeShown()); | |||
| setBounds (characterArea.withWidth (2)); | |||
| } | |||
| @@ -31,8 +31,7 @@ namespace juce | |||
| @tags{GUI} | |||
| */ | |||
| class JUCE_API CaretComponent : public Component, | |||
| private Timer | |||
| class JUCE_API CaretComponent : public Component | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -73,7 +72,6 @@ private: | |||
| Component* owner; | |||
| bool shouldBeShown() const; | |||
| void timerCallback() override; | |||
| JUCE_DECLARE_NON_COPYABLE (CaretComponent) | |||
| }; | |||
| @@ -271,23 +271,6 @@ void ComponentBoundsConstrainer::checkBounds (Rectangle<int>& bounds, | |||
| bounds.setWidth (roundToInt (bounds.getHeight() * aspectRatio)); | |||
| } | |||
| } | |||
| if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight)) | |||
| { | |||
| bounds.setX (old.getX() + (old.getWidth() - bounds.getWidth()) / 2); | |||
| } | |||
| else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom)) | |||
| { | |||
| bounds.setY (old.getY() + (old.getHeight() - bounds.getHeight()) / 2); | |||
| } | |||
| else | |||
| { | |||
| if (isStretchingLeft) | |||
| bounds.setX (old.getRight() - bounds.getWidth()); | |||
| if (isStretchingTop) | |||
| bounds.setY (old.getBottom() - bounds.getHeight()); | |||
| } | |||
| } | |||
| jassert (! bounds.isEmpty()); | |||
| @@ -41,8 +41,6 @@ LookAndFeel_V1::LookAndFeel_V1() | |||
| setColour (PopupMenu::highlightedBackgroundColourId, Colour (0xbfa4c2ce)); | |||
| setColour (PopupMenu::highlightedTextColourId, Colours::black); | |||
| setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId)); | |||
| scrollbarShadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 2, Point<int>())); | |||
| } | |||
| LookAndFeel_V1::~LookAndFeel_V1() | |||
| @@ -291,7 +289,7 @@ void LookAndFeel_V1::drawScrollbar (Graphics& g, ScrollBar& bar, | |||
| ImageEffectFilter* LookAndFeel_V1::getScrollbarEffect() | |||
| { | |||
| return &scrollbarShadow; | |||
| return nullptr; | |||
| } | |||
| @@ -477,7 +475,7 @@ Button* LookAndFeel_V1::createSliderButton (Slider&, const bool isIncrement) | |||
| ImageEffectFilter* LookAndFeel_V1::getSliderEffect (Slider&) | |||
| { | |||
| return &scrollbarShadow; | |||
| return nullptr; | |||
| } | |||
| int LookAndFeel_V1::getSliderThumbRadius (Slider&) | |||
| @@ -97,8 +97,6 @@ public: | |||
| bool positionTitleBarButtonsOnLeft) override; | |||
| private: | |||
| DropShadowEffect scrollbarShadow; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V1) | |||
| }; | |||
| @@ -1292,8 +1292,6 @@ void LookAndFeel_V4::drawCallOutBoxBackground (CallOutBox& box, Graphics& g, | |||
| { | |||
| cachedImage = { Image::ARGB, box.getWidth(), box.getHeight(), true }; | |||
| Graphics g2 (cachedImage); | |||
| DropShadow (Colours::black.withAlpha (0.7f), 8, { 0, 2 }).drawForPath (g2, path); | |||
| } | |||
| g.setColour (Colours::black); | |||
| @@ -30,9 +30,6 @@ BubbleComponent::BubbleComponent() | |||
| : allowablePlacements (above | below | left | right) | |||
| { | |||
| setInterceptsMouseClicks (false, false); | |||
| shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.35f), 5, Point<int>())); | |||
| setComponentEffect (&shadow); | |||
| } | |||
| BubbleComponent::~BubbleComponent() {} | |||
| @@ -178,7 +178,6 @@ private: | |||
| Rectangle<int> content; | |||
| Point<int> arrowTip; | |||
| int allowablePlacements; | |||
| DropShadowEffect shadow; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BubbleComponent) | |||
| }; | |||
| @@ -61,7 +61,7 @@ public: | |||
| { | |||
| if (auto* peer = comp.getPeer()) | |||
| { | |||
| pos = peer->globalToLocal (pos); | |||
| pos = peer->globalToLocal (pos) * comp.getTotalPixelScaling(); | |||
| auto& peerComp = peer->getComponent(); | |||
| return comp.getLocalPoint (&peerComp, ScalingHelpers::unscaledScreenPosToScaled (peerComp, pos)); | |||
| } | |||
| @@ -1816,7 +1816,7 @@ public: | |||
| if (peerIsDeleted) | |||
| return S_FALSE; | |||
| peer.handleDragExit (dragInfo); | |||
| peer.handleDragDrop (dragInfo); | |||
| return S_OK; | |||
| } | |||
| @@ -749,7 +749,7 @@ public: | |||
| ? e.position.x - mouseDragStartPos.x | |||
| : mouseDragStartPos.y - e.position.y; | |||
| newPos = owner.valueToProportionOfLength (valueOnMouseDown) | |||
| newPos = owner.valueToProportionOfLength (valueWhenLastDragged) | |||
| + mouseDiff * (1.0 / pixelsForFullDragExtent); | |||
| if (style == IncDecButtons) | |||
| @@ -763,7 +763,7 @@ public: | |||
| auto mouseDiff = (e.position.x - mouseDragStartPos.x) | |||
| + (mouseDragStartPos.y - e.position.y); | |||
| newPos = owner.valueToProportionOfLength (valueOnMouseDown) | |||
| newPos = owner.valueToProportionOfLength (valueWhenLastDragged) | |||
| + mouseDiff * (1.0 / pixelsForFullDragExtent); | |||
| } | |||
| else | |||
| @@ -774,6 +774,7 @@ public: | |||
| newPos = 1.0 - newPos; | |||
| } | |||
| mouseDragStartPos = e.position; | |||
| newPos = (isRotary() && ! rotaryParams.stopAtEnd) ? newPos - std::floor (newPos) | |||
| : jlimit (0.0, 1.0, newPos); | |||
| valueWhenLastDragged = owner.proportionOfLengthToValue (newPos); | |||
| @@ -833,6 +833,11 @@ struct TextEditor::TextHolderComponent : public Component, | |||
| { | |||
| owner.drawContent (g); | |||
| } | |||
| void setTopLeftPosition(Point<int> new_position) override { | |||
| Component::setTopLeftPosition(new_position); | |||
| owner.textChanged(); | |||
| } | |||
| void restartTimer() | |||
| { | |||
| @@ -1558,6 +1563,9 @@ void TextEditor::moveCaretTo (const int newPosition, const bool isSelecting) | |||
| moveCaret (newPosition); | |||
| selection = Range<int>::emptyRange (getCaretPosition()); | |||
| } | |||
| if (listeners.size() != 0 || onTextChange != nullptr) | |||
| postCommandMessage (TextEditorDefs::textChangeMessageId); | |||
| } | |||
| int TextEditor::getTextIndexAt (const int x, const int y) | |||
| @@ -2141,6 +2149,9 @@ void TextEditor::focusGained (FocusChangeType cause) | |||
| repaint(); | |||
| updateCaretPosition(); | |||
| if (listeners.size() != 0 || onTextChange != nullptr) | |||
| postCommandMessage (TextEditorDefs::textChangeMessageId); | |||
| } | |||
| void TextEditor::focusLost (FocusChangeType) | |||
| @@ -474,7 +474,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | |||
| if (DragHelpers::isSuitableTarget (info, newTarget)) | |||
| { | |||
| dragAndDropTargetComponent = newTarget; | |||
| auto pos = newTarget->getLocalPoint (&component, info.position); | |||
| auto pos = newTarget->getLocalPoint (&component, info.position * newTarget->getTotalPixelScaling()); | |||
| if (DragHelpers::isFileDrag (info)) | |||
| dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragEnter (info.files, pos.x, pos.y); | |||
| @@ -491,7 +491,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | |||
| if (! DragHelpers::isSuitableTarget (info, newTarget)) | |||
| return false; | |||
| auto pos = newTarget->getLocalPoint (&component, info.position); | |||
| auto pos = newTarget->getLocalPoint (&component, info.position * newTarget->getTotalPixelScaling()); | |||
| if (DragHelpers::isFileDrag (info)) | |||
| dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragMove (info.files, pos.x, pos.y); | |||
| @@ -124,7 +124,7 @@ | |||
| It's mandatory in OpenGL 3.0 to specify the GLSL version. | |||
| */ | |||
| #if JUCE_OPENGL3 | |||
| #if JUCE_OPENGL_ES | |||
| #if JUCE_OPENGL_ES || OPENGL_ES | |||
| #define JUCE_GLSL_VERSION "#version 300 es" | |||
| #else | |||
| #define JUCE_GLSL_VERSION "#version 150" | |||
| @@ -126,6 +126,14 @@ enum MissingOpenGLDefinitions | |||
| GL_DYNAMIC_DRAW = 0x88E8, | |||
| GL_STREAM_DRAW = 0x88E0, | |||
| GL_GEOMETRY_SHADER = 0x8DD9, | |||
| GL_LINE_STRIP_ADJACENCY = 0x000B, | |||
| GL_INTERLEAVED_ATTRIBS = 0x8C8C, | |||
| GL_STATIC_READ = 0x88E5, | |||
| GL_TRANSFORM_FEEDBACK_BUFFER = 0x8C8E, | |||
| GL_RASTERIZER_DISCARD = 0x8C89, | |||
| GL_MAP_READ_BIT = 0x0001, | |||
| WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000, | |||
| WGL_DRAW_TO_WINDOW_ARB = 0x2001, | |||
| WGL_ACCELERATION_ARB = 0x2003, | |||
| @@ -83,7 +83,13 @@ namespace juce | |||
| USE_FUNCTION (glCheckFramebufferStatus, GLenum, (GLenum p1), (p1))\ | |||
| USE_FUNCTION (glFramebufferTexture2D, void, (GLenum p1, GLenum p2, GLenum p3, GLuint p4, GLint p5), (p1, p2, p3, p4, p5))\ | |||
| USE_FUNCTION (glFramebufferRenderbuffer, void, (GLenum p1, GLenum p2, GLenum p3, GLuint p4), (p1, p2, p3, p4))\ | |||
| USE_FUNCTION (glGetFramebufferAttachmentParameteriv, void, (GLenum p1, GLenum p2, GLenum p3, GLint* p4), (p1, p2, p3, p4)) | |||
| USE_FUNCTION (glGetFramebufferAttachmentParameteriv, void, (GLenum p1, GLenum p2, GLenum p3, GLint* p4), (p1, p2, p3, p4))\ | |||
| USE_FUNCTION (glTransformFeedbackVaryings, void, (GLuint p1, GLsizei p2, const char **p3, GLenum p4), (p1, p2, p3, p4))\ | |||
| USE_FUNCTION (glBeginTransformFeedback, void, (GLenum p1), (p1))\ | |||
| USE_FUNCTION (glEndTransformFeedback, void, (), ())\ | |||
| USE_FUNCTION (glBindBufferBase, void, (GLenum p1, GLuint p2, GLuint p3), (p1, p2, p3))\ | |||
| USE_FUNCTION (glMapBufferRange, void*, (GLenum p1, GLintptr p2, GLsizeiptr p3, GLbitfield p4), (p1, p2, p3, p4))\ | |||
| USE_FUNCTION (glUnmapBuffer, GLboolean, (GLenum p1), (p1)); | |||
| /** @internal This macro contains a list of GL extension functions that need to be dynamically loaded on Windows/Linux. | |||
| @see OpenGLExtensionFunctions | |||
| @@ -69,8 +69,8 @@ public: | |||
| GLint attribs[] = | |||
| { | |||
| GLX_RGBA, | |||
| GLX_DOUBLEBUFFER, | |||
| GLX_RENDER_TYPE, GLX_RGBA_BIT, | |||
| GLX_DOUBLEBUFFER, True, | |||
| GLX_RED_SIZE, cPixelFormat.redBits, | |||
| GLX_GREEN_SIZE, cPixelFormat.greenBits, | |||
| GLX_BLUE_SIZE, cPixelFormat.blueBits, | |||
| @@ -81,13 +81,21 @@ public: | |||
| GLX_ACCUM_GREEN_SIZE, cPixelFormat.accumulationBufferGreenBits, | |||
| GLX_ACCUM_BLUE_SIZE, cPixelFormat.accumulationBufferBlueBits, | |||
| GLX_ACCUM_ALPHA_SIZE, cPixelFormat.accumulationBufferAlphaBits, | |||
| GLX_X_RENDERABLE, True, | |||
| None | |||
| }; | |||
| bestVisual = glXChooseVisual (display, X11Symbols::getInstance()->xDefaultScreen (display), attribs); | |||
| if (bestVisual == nullptr) | |||
| int countFbConfigs; | |||
| fbConfig = glXChooseFBConfig (display, DefaultScreen (display), attribs, &countFbConfigs); | |||
| if (fbConfig == nullptr) | |||
| return; | |||
| bestVisual = glXGetVisualFromFBConfig (display, *fbConfig); | |||
| if (bestVisual == nullptr) { | |||
| X11Symbols::getInstance()->xFree (fbConfig); | |||
| return; | |||
| } | |||
| auto* peer = component.getPeer(); | |||
| jassert (peer != nullptr); | |||
| @@ -148,6 +156,9 @@ public: | |||
| } | |||
| } | |||
| if (fbConfig != nullptr) | |||
| X11Symbols::getInstance()->xFree (fbConfig); | |||
| if (bestVisual != nullptr) | |||
| X11Symbols::getInstance()->xFree (bestVisual); | |||
| } | |||
| @@ -155,7 +166,18 @@ public: | |||
| bool initialiseOnRenderThread (OpenGLContext& c) | |||
| { | |||
| XWindowSystemUtilities::ScopedXLock xLock; | |||
| renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE); | |||
| PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribs; | |||
| int attribs[] = { | |||
| GLX_CONTEXT_MAJOR_VERSION_ARB, 3, | |||
| GLX_CONTEXT_MINOR_VERSION_ARB, 2, | |||
| GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, | |||
| 0 | |||
| }; | |||
| createContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) | |||
| OpenGLHelpers::getExtensionFunction("glXCreateContextAttribsARB"); | |||
| renderContext = createContextAttribs (display, *fbConfig, (GLXContext) contextToShareWith, GL_TRUE, attribs); | |||
| c.makeActive(); | |||
| context = &c; | |||
| @@ -251,6 +273,7 @@ private: | |||
| int swapFrames = 1; | |||
| Rectangle<int> bounds; | |||
| XVisualInfo* bestVisual = nullptr; | |||
| GLXFBConfig* fbConfig = nullptr; | |||
| void* contextToShareWith; | |||
| OpenGLContext* context = nullptr; | |||
| @@ -290,6 +290,8 @@ private: | |||
| atts[n++] = WGL_DRAW_TO_WINDOW_ARB; atts[n++] = GL_TRUE; | |||
| atts[n++] = WGL_SUPPORT_OPENGL_ARB; atts[n++] = GL_TRUE; | |||
| atts[n++] = WGL_CONTEXT_MAJOR_VERSION_ARB; atts[n++] = 3; | |||
| atts[n++] = WGL_CONTEXT_MINOR_VERSION_ARB; atts[n++] = 2; | |||
| atts[n++] = WGL_DOUBLE_BUFFER_ARB; atts[n++] = GL_TRUE; | |||
| atts[n++] = WGL_PIXEL_TYPE_ARB; atts[n++] = WGL_TYPE_RGBA_ARB; | |||
| atts[n++] = WGL_ACCELERATION_ARB; | |||
| @@ -83,7 +83,7 @@ void OpenGLHelpers::enableScissorTest (Rectangle<int> clip) | |||
| String OpenGLHelpers::translateVertexShaderToV3 (const String& code) | |||
| { | |||
| #if JUCE_OPENGL3 | |||
| #if JUCE_OPENGL3 || OPENGL_ES | |||
| if (OpenGLShaderProgram::getLanguageVersion() > 1.2) | |||
| { | |||
| String output; | |||
| @@ -119,7 +119,7 @@ String OpenGLHelpers::translateVertexShaderToV3 (const String& code) | |||
| String OpenGLHelpers::translateFragmentShaderToV3 (const String& code) | |||
| { | |||
| #if JUCE_OPENGL3 | |||
| #if JUCE_OPENGL3 || OPENGL_ES | |||
| if (OpenGLShaderProgram::getLanguageVersion() > 1.2) | |||
| return JUCE_GLSL_VERSION "\n" | |||
| "out " JUCE_MEDIUMP " vec4 fragColor;\n" | |||