diff --git a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj index f9c32d1bd4..5022108bd1 100644 --- a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj @@ -195,6 +195,7 @@ 2820D74789660269902DB93A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Uuid.cpp"; path = "../../../../modules/juce_core/misc/juce_Uuid.cpp"; sourceTree = "SOURCE_ROOT"; }; 282C1DA3A161FEF2AD6F94A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CodeTokeniser.h"; path = "../../../../modules/juce_gui_extra/code_editor/juce_CodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; 2954678FE7AB78F318FBD4F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputStream.h"; path = "../../../../modules/juce_core/files/juce_FileInputStream.h"; sourceTree = "SOURCE_ROOT"; }; + 295A470694011EBCA802822B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLGraphicsContext.cpp"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; 2968B26144E09D6A6659E739 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DirectShowComponent.h"; path = "../../../../modules/juce_video/playback/juce_DirectShowComponent.h"; sourceTree = "SOURCE_ROOT"; }; 2A835EF38887CAB750B49AC6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativePointPath.h"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativePointPath.h"; sourceTree = "SOURCE_ROOT"; }; 2ACD67859FBC33EB743708CB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextButton.h"; path = "../../../../modules/juce_gui_basics/buttons/juce_TextButton.h"; sourceTree = "SOURCE_ROOT"; }; @@ -624,6 +625,7 @@ A6FCBC9721E7FC9DE30B6DC4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Midi.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_linux_Midi.cpp"; sourceTree = "SOURCE_ROOT"; }; A72FB74D13AA5C6A472E9E82 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChangeBroadcaster.cpp"; path = "../../../../modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp"; sourceTree = "SOURCE_ROOT"; }; A763E7AF50D548D8C4A4C3D1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioDeviceManager.h"; path = "../../../../modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h"; sourceTree = "SOURCE_ROOT"; }; + A7B3B265DACC82D9E9CFB3DA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGLGraphicsContext.h"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h"; sourceTree = "SOURCE_ROOT"; }; A7BD5AB895B2531A75FE0268 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BufferingAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_BufferingAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; A7F413D4C880363878469E5A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_JSON.h"; path = "../../../../modules/juce_core/json/juce_JSON.h"; sourceTree = "SOURCE_ROOT"; }; A80CC48B8215D447643CA411 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ToolbarItemFactory.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemFactory.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1869,6 +1871,8 @@ 8878426C7F58CB22969E7133, AC3EFDDC80761A45E8BE0624, 43E4604C39E9A992216F6B98, + 295A470694011EBCA802822B, + A7B3B265DACC82D9E9CFB3DA, D7239D5B984E07808E2DB28C, D2C40CDF46D894BFC72BDC56, E46977801F19277F4D3B324B, diff --git a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj index 9ebe58ca6d..f49513f88c 100644 --- a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj @@ -4220,6 +4220,17 @@ + + + + + + + + + diff --git a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj index 7c982899bd..84cb693340 100644 --- a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj @@ -4220,6 +4220,17 @@ + + + + + + + + + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj index e0d88e7227..2ee0b709bb 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj @@ -1133,6 +1133,9 @@ true + + true + true @@ -1578,6 +1581,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters index ff3a96bcaa..9db7eaca1c 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters @@ -1486,6 +1486,9 @@ Juce Modules\juce_opengl\opengl + + Juce Modules\juce_opengl\opengl + Juce Modules\juce_opengl\opengl @@ -2775,6 +2778,9 @@ Juce Modules\juce_opengl\opengl + + Juce Modules\juce_opengl\opengl + Juce Modules\juce_opengl\opengl diff --git a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj index 7c84ef9557..693c8d2694 100644 --- a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj @@ -188,6 +188,7 @@ 2820D74789660269902DB93A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Uuid.cpp"; path = "../../../../modules/juce_core/misc/juce_Uuid.cpp"; sourceTree = "SOURCE_ROOT"; }; 282C1DA3A161FEF2AD6F94A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CodeTokeniser.h"; path = "../../../../modules/juce_gui_extra/code_editor/juce_CodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; 2954678FE7AB78F318FBD4F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputStream.h"; path = "../../../../modules/juce_core/files/juce_FileInputStream.h"; sourceTree = "SOURCE_ROOT"; }; + 295A470694011EBCA802822B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLGraphicsContext.cpp"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; 2968B26144E09D6A6659E739 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DirectShowComponent.h"; path = "../../../../modules/juce_video/playback/juce_DirectShowComponent.h"; sourceTree = "SOURCE_ROOT"; }; 2A835EF38887CAB750B49AC6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativePointPath.h"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativePointPath.h"; sourceTree = "SOURCE_ROOT"; }; 2ACD67859FBC33EB743708CB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextButton.h"; path = "../../../../modules/juce_gui_basics/buttons/juce_TextButton.h"; sourceTree = "SOURCE_ROOT"; }; @@ -616,6 +617,7 @@ A6FCBC9721E7FC9DE30B6DC4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Midi.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_linux_Midi.cpp"; sourceTree = "SOURCE_ROOT"; }; A72FB74D13AA5C6A472E9E82 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChangeBroadcaster.cpp"; path = "../../../../modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp"; sourceTree = "SOURCE_ROOT"; }; A763E7AF50D548D8C4A4C3D1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioDeviceManager.h"; path = "../../../../modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h"; sourceTree = "SOURCE_ROOT"; }; + A7B3B265DACC82D9E9CFB3DA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGLGraphicsContext.h"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h"; sourceTree = "SOURCE_ROOT"; }; A7BD5AB895B2531A75FE0268 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BufferingAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_BufferingAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; A7F413D4C880363878469E5A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_JSON.h"; path = "../../../../modules/juce_core/json/juce_JSON.h"; sourceTree = "SOURCE_ROOT"; }; A80CC48B8215D447643CA411 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ToolbarItemFactory.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemFactory.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1859,6 +1861,8 @@ 8878426C7F58CB22969E7133, AC3EFDDC80761A45E8BE0624, 43E4604C39E9A992216F6B98, + 295A470694011EBCA802822B, + A7B3B265DACC82D9E9CFB3DA, D7239D5B984E07808E2DB28C, D2C40CDF46D894BFC72BDC56, E46977801F19277F4D3B324B, diff --git a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp index fdc3a0122e..ee1f4a8e2a 100644 --- a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp +++ b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp @@ -133,7 +133,7 @@ private: // Functions to create a couple of images to use as textures.. static Image createImage1() { - Image image (new OpenGLFrameBufferImage (Image::ARGB, 256, 256)); + Image image (new OpenGLFrameBufferImage (256, 256)); Graphics g (image); @@ -148,7 +148,7 @@ private: static Image createImage2() { - Image image (new OpenGLFrameBufferImage (Image::ARGB, 128, 128)); + Image image (new OpenGLFrameBufferImage (128, 128)); Graphics g (image); g.fillAll (Colours::darkred.withAlpha (0.7f)); diff --git a/extras/audio plugin host/Builds/MacOSX/Plugin Host.xcodeproj/project.pbxproj b/extras/audio plugin host/Builds/MacOSX/Plugin Host.xcodeproj/project.pbxproj index 7a0e39bda5..15e42d017c 100644 --- a/extras/audio plugin host/Builds/MacOSX/Plugin Host.xcodeproj/project.pbxproj +++ b/extras/audio plugin host/Builds/MacOSX/Plugin Host.xcodeproj/project.pbxproj @@ -260,6 +260,7 @@ 3ED29A00C88C8C3B8B3DE56D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ShapeButton.h"; path = "../../../../modules/juce_gui_basics/buttons/juce_ShapeButton.h"; sourceTree = "SOURCE_ROOT"; }; 3ED373A6B2C53518BAA012E6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativeRectangle.cpp"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp"; sourceTree = "SOURCE_ROOT"; }; 3EFBFA5735C496DC209ED1CE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_win32_HiddenMessageWindow.h"; path = "../../../../modules/juce_events/native/juce_win32_HiddenMessageWindow.h"; sourceTree = "SOURCE_ROOT"; }; + 3F263028F4926C6F3318E6A4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLGraphicsContext.cpp"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; 3F924E9D75C642D0A14828E8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativePointPath.cpp"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp"; sourceTree = "SOURCE_ROOT"; }; 3F963B869D58A34E97922E97 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativePointPath.h"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativePointPath.h"; sourceTree = "SOURCE_ROOT"; }; 410A767D64DBE4AB92D56251 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextButton.h"; path = "../../../../modules/juce_gui_basics/buttons/juce_TextButton.h"; sourceTree = "SOURCE_ROOT"; }; @@ -856,6 +857,7 @@ FE79AFFDB5029AC6AE7F4CFC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RecentlyOpenedFilesList.h"; path = "../../../../modules/juce_gui_extra/misc/juce_RecentlyOpenedFilesList.h"; sourceTree = "SOURCE_ROOT"; }; FE7C03DACFC725D712D9F508 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_utils.mm"; path = "../../../../modules/juce_audio_utils/juce_audio_utils.mm"; sourceTree = "SOURCE_ROOT"; }; FEB2517E7420B23086B6580B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MenuBarModel.cpp"; path = "../../../../modules/juce_gui_basics/menus/juce_MenuBarModel.cpp"; sourceTree = "SOURCE_ROOT"; }; + FF28173366C5BCF1BAE2CEA9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGLGraphicsContext.h"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h"; sourceTree = "SOURCE_ROOT"; }; FFC1C8C289D7D3FF39865E40 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImageComponent.cpp"; path = "../../../../modules/juce_gui_basics/widgets/juce_ImageComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; FFD8E80D93D1005D5983C057 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ToolbarItemFactory.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemFactory.h"; sourceTree = "SOURCE_ROOT"; }; FFFA6E3ECEFDF1DE95D0F632 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_JackAudio.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_linux_JackAudio.cpp"; sourceTree = "SOURCE_ROOT"; }; @@ -1791,6 +1793,8 @@ BE0231D93CBB02BBC2704D1D, 43D23C18695F24F9A3DFA7B4, 438CA87567F47F9AF39788D1, + 3F263028F4926C6F3318E6A4, + FF28173366C5BCF1BAE2CEA9, 153D339EB2CCEC711215AD04, 9B4278735225CBEED635FF03, C0EECABDA5446EAD76E2578F, diff --git a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj index 9eca1ce9af..3860e9871b 100644 --- a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj @@ -4143,6 +4143,17 @@ + + + + + + + + + diff --git a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj index e1368cfb59..c23e1c5af5 100644 --- a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj @@ -4143,6 +4143,17 @@ + + + + + + + + + diff --git a/extras/static library/Builds/MacOSX/juce.xcodeproj/project.pbxproj b/extras/static library/Builds/MacOSX/juce.xcodeproj/project.pbxproj index fe79b14fd5..957a63724b 100644 --- a/extras/static library/Builds/MacOSX/juce.xcodeproj/project.pbxproj +++ b/extras/static library/Builds/MacOSX/juce.xcodeproj/project.pbxproj @@ -642,6 +642,7 @@ CDF3D87F97FF1526499CC3A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Registry.cpp"; path = "../../../../modules/juce_core/native/juce_win32_Registry.cpp"; sourceTree = "SOURCE_ROOT"; }; CE55DEAD4829A44E6F68EBA3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_opengl.mm"; path = "../../../../modules/juce_opengl/juce_opengl.mm"; sourceTree = "SOURCE_ROOT"; }; CE598F0D6317056C9958D8DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChangeListener.h"; path = "../../../../modules/juce_events/broadcasters/juce_ChangeListener.h"; sourceTree = "SOURCE_ROOT"; }; + CEBE83A5D278021237C24D66 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLGraphicsContext.cpp"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; CEEB08E0152E40C0F7F7D9ED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DynamicLibrary.h"; path = "../../../../modules/juce_core/threads/juce_DynamicLibrary.h"; sourceTree = "SOURCE_ROOT"; }; CF16F0D87956060986A260CE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TreeView.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_TreeView.h"; sourceTree = "SOURCE_ROOT"; }; CF234664EFB623E0E51BF84F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioUnitPluginFormat.h"; path = "../../../../modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h"; sourceTree = "SOURCE_ROOT"; }; @@ -683,6 +684,7 @@ D9725F490FFF28EE21FAE674 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageEffectFilter.h"; path = "../../../../modules/juce_graphics/effects/juce_ImageEffectFilter.h"; sourceTree = "SOURCE_ROOT"; }; D974DED975BAB28D7E4DD088 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioTransportSource.h"; path = "../../../../modules/juce_audio_devices/sources/juce_AudioTransportSource.h"; sourceTree = "SOURCE_ROOT"; }; D9A6F0D617C0DFE739401654 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ButtonPropertyComponent.h"; path = "../../../../modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; }; + D9A93A1A24319A4E650E53B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGLGraphicsContext.h"; path = "../../../../modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h"; sourceTree = "SOURCE_ROOT"; }; D9C8927A19B0A1D2AF2304B8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../../../modules/juce_events/native/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; }; D9D8C7CDA1EA11E65E539C00 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableCornerComponent.h"; path = "../../../../modules/juce_gui_basics/layout/juce_ResizableCornerComponent.h"; sourceTree = "SOURCE_ROOT"; }; D9F02568E68C40FADFE9210F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FlacAudioFormat.cpp"; path = "../../../../modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp"; sourceTree = "SOURCE_ROOT"; }; @@ -1710,6 +1712,8 @@ 6096E343983724F254B268C3, 73C6ABF23C4B143DB2BC7226, 9D4FC9BEE122256B2557D088, + CEBE83A5D278021237C24D66, + D9A93A1A24319A4E650E53B2, 92346B7BA7AFD6750405F6F3, AEB9A6FBC99A1C710C51D799, 6DCD8800E380DB691DC9D467, diff --git a/extras/static library/Builds/VisualStudio2008/juce.vcproj b/extras/static library/Builds/VisualStudio2008/juce.vcproj index 6618ab9bfa..3f24242da0 100644 --- a/extras/static library/Builds/VisualStudio2008/juce.vcproj +++ b/extras/static library/Builds/VisualStudio2008/juce.vcproj @@ -4034,6 +4034,17 @@ + + + + + + + + + diff --git a/extras/static library/Builds/VisualStudio2010/juce.vcxproj b/extras/static library/Builds/VisualStudio2010/juce.vcxproj index 9157b2e939..5b202f8414 100644 --- a/extras/static library/Builds/VisualStudio2010/juce.vcxproj +++ b/extras/static library/Builds/VisualStudio2010/juce.vcxproj @@ -1096,6 +1096,9 @@ true + + true + true @@ -1524,6 +1527,7 @@ + diff --git a/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters b/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters index b7382117a7..7b628553cd 100644 --- a/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters +++ b/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters @@ -1372,6 +1372,9 @@ Juce Modules\juce_opengl\opengl + + Juce Modules\juce_opengl\opengl + Juce Modules\juce_opengl\opengl @@ -2610,6 +2613,9 @@ Juce Modules\juce_opengl\opengl + + Juce Modules\juce_opengl\opengl + Juce Modules\juce_opengl\opengl diff --git a/modules/juce_opengl/juce_opengl.cpp b/modules/juce_opengl/juce_opengl.cpp index 2924319f5f..60893ebb85 100644 --- a/modules/juce_opengl/juce_opengl.cpp +++ b/modules/juce_opengl/juce_opengl.cpp @@ -132,6 +132,7 @@ // START_AUTOINCLUDE opengl/*.cpp #include "opengl/juce_OpenGLComponent.cpp" #include "opengl/juce_OpenGLFrameBuffer.cpp" +#include "opengl/juce_OpenGLGraphicsContext.cpp" #include "opengl/juce_OpenGLHelpers.cpp" #include "opengl/juce_OpenGLImage.cpp" #include "opengl/juce_OpenGLTexture.cpp" diff --git a/modules/juce_opengl/juce_opengl.h b/modules/juce_opengl/juce_opengl.h index e82a054523..3a81426c23 100644 --- a/modules/juce_opengl/juce_opengl.h +++ b/modules/juce_opengl/juce_opengl.h @@ -29,10 +29,7 @@ #include "../juce_gui_extra/juce_gui_extra.h" #undef JUCE_OPENGL - -#if ! JUCE_ANDROID - #define JUCE_OPENGL 1 -#endif +#define JUCE_OPENGL 1 #if JUCE_IOS || JUCE_ANDROID #define JUCE_OPENGL_ES 1 @@ -95,6 +92,9 @@ BEGIN_JUCE_NAMESPACE #ifndef __JUCE_OPENGLFRAMEBUFFER_JUCEHEADER__ #include "opengl/juce_OpenGLFrameBuffer.h" #endif +#ifndef __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__ + #include "opengl/juce_OpenGLGraphicsContext.h" +#endif #ifndef __JUCE_OPENGLHELPERS_JUCEHEADER__ #include "opengl/juce_OpenGLHelpers.h" #endif diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp new file mode 100644 index 0000000000..774fed6841 --- /dev/null +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -0,0 +1,1199 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +BEGIN_JUCE_NAMESPACE + +namespace +{ + void applyFlippedMatrix (int x, int y, int width, int height) + { + OpenGLHelpers::prepareFor2D (width, height); + OpenGLHelpers::applyTransform (AffineTransform::translation ((float) -x, (float) -y) + .followedBy (AffineTransform::verticalFlip ((float) height))); + } +} + +struct OpenGLTarget +{ + OpenGLTarget (GLuint frameBufferID_, int width_, int height_) noexcept + : frameBuffer (nullptr), frameBufferID (frameBufferID_), + x (0), y (0), width (width_), height (height_) + {} + + OpenGLTarget (OpenGLFrameBuffer& frameBuffer_, const Point& origin) noexcept + : frameBuffer (&frameBuffer_), frameBufferID (0), x (origin.getX()), y (origin.getY()), + width (frameBuffer_.getWidth()), height (frameBuffer_.getHeight()) + {} + + OpenGLTarget (const OpenGLTarget& other) noexcept + : frameBuffer (other.frameBuffer), frameBufferID (other.frameBufferID), + x (other.x), y (other.y), width (other.width), height (other.height) + {} + + void makeActiveFor2D() const + { + if (frameBuffer != nullptr) + frameBuffer->makeCurrentRenderingTarget(); + else + OpenGLFrameBuffer::setCurrentFrameBufferTarget (frameBufferID); + + applyFlippedMatrix (x, y, width, height); + glDisable (GL_DEPTH_TEST); + } + + void scissor (Rectangle r) const + { + r = r.translated (-x, -y); + OpenGLHelpers::enableScissorTest (r.withY (height - r.getBottom())); + } + + OpenGLFrameBuffer* frameBuffer; + GLuint frameBufferID; + int x, y, width, height; +}; + +//============================================================================== +namespace +{ + enum { defaultOversamplingLevel = 4 }; + + void fillRectangleList (const RectangleList& list) + { + glEnableClientState (GL_VERTEX_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + + GLfloat vertices [8]; + glVertexPointer (2, GL_FLOAT, 0, vertices); + + for (RectangleList::Iterator i (list); i.next();) + { + vertices[0] = vertices[4] = (GLfloat) i.getRectangle()->getX(); + vertices[1] = vertices[3] = (GLfloat) i.getRectangle()->getY(); + vertices[2] = vertices[6] = (GLfloat) i.getRectangle()->getRight(); + vertices[5] = vertices[7] = (GLfloat) i.getRectangle()->getBottom(); + + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + } + } + + inline void setColour (const float alpha) noexcept + { + 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& 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 sourceOrigin, const bool shouldMaskRGB) + { + 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); + } + + void renderPath (const Path& path, const AffineTransform& transform, int oversamplingLevel) + { + glEnableClientState (GL_VERTEX_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + + TriangulatedPath (path, transform).draw (oversamplingLevel); + } + + void setNormalBlendingMode() noexcept + { + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + void setBlendMode (const bool replaceExistingContents) noexcept + { + if (replaceExistingContents) + glDisable (GL_BLEND); + else + setNormalBlendingMode(); + } + + void fillRectWithTiledTexture (const OpenGLTarget& target, int textureWidth, int textureHeight, + const Rectangle& 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); + + static bool canDoNonPowerOfTwos = OpenGLHelpers::isExtensionSupported ("GL_ARB_texture_non_power_of_two"); + + if (canDoNonPowerOfTwos || (isPowerOfTwo (textureWidth) && isPowerOfTwo (textureHeight))) + { + 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); + } + else + { + // For hardware that can't handle non-power-of-two textures, this is a fallback algorithm + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + target.scissor (clip); + glPushMatrix(); + OpenGLHelpers::applyTransform (transform); + + GLfloat vertices[8]; + const GLfloat textureCoords[] = { 0, 0, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f }; + glVertexPointer (2, GL_FLOAT, 0, vertices); + glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); + + const Rectangle targetArea (clip.transformed (transform.inverted())); + int x = targetArea.getX() - negativeAwareModulo (targetArea.getX(), textureWidth); + int y = targetArea.getY() - negativeAwareModulo (targetArea.getY(), textureHeight); + const int right = targetArea.getRight(); + const int bottom = targetArea.getBottom(); + + while (y < bottom) + { + vertices[1] = vertices[3] = (GLfloat) y; + vertices[5] = vertices[7] = (GLfloat) (y + textureHeight); + + for (int x1 = x; x1 < right; x1 += textureWidth) + { + vertices[0] = vertices[4] = (GLfloat) x1; + vertices[2] = vertices[6] = (GLfloat) (x1 + textureWidth); + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + } + + y += textureHeight; + } + + glPopMatrix(); + glDisable (GL_SCISSOR_TEST); + } + } + + void fillWithLinearGradient (const Rectangle& rect, + const ColourGradient& grad, + const AffineTransform& transform, + const int textureSize) + { + const Point p1 (grad.point1.transformedBy (transform)); + const Point p2 (grad.point2.transformedBy (transform)); + const Point p3 (Point (grad.point1.getX() - (grad.point2.getY() - grad.point1.getY()) / textureSize, + grad.point1.getY() + (grad.point2.getX() - grad.point1.getX()) / textureSize).transformedBy (transform)); + + const AffineTransform textureTransform (AffineTransform::fromTargetPoints (p1.getX(), p1.getY(), 0.0f, 0.0f, + p2.getX(), p2.getY(), 1.0f, 0.0f, + p3.getX(), p3.getY(), 0.0f, 1.0f)); + + 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 }; + GLfloat textureCoords[] = { l, t, r, t, l, b, r, b }; + + textureTransform.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); + textureTransform.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); + + drawTriangleStrip (vertices, textureCoords, 4); + } + + void fillWithRadialGradient (const OpenGLTarget& target, const Rectangle& rect, + const ColourGradient& grad, const AffineTransform& transform) + { + const Point centre (grad.point1.transformedBy (transform)); + + const float screenRadius = centre.getDistanceFrom (rect.getCentre().toFloat()) + + Point (rect.getWidth() / 2, + rect.getHeight() / 2).getDistanceFromOrigin() + + 8.0f; + + const AffineTransform inverse (transform.inverted()); + const float sourceRadius = jmax (Point (screenRadius, 0.0f).transformedBy (inverse).getDistanceFromOrigin(), + Point (0.0f, screenRadius).transformedBy (inverse).getDistanceFromOrigin()); + + const int numDivisions = 90; + GLfloat vertices [4 + numDivisions * 2]; + GLfloat textureCoords [4 + numDivisions * 2]; + + { + GLfloat* t = textureCoords; + *t++ = 0.0f; + *t++ = 0.0f; + + const GLfloat texturePos = sourceRadius / grad.point1.getDistanceFrom (grad.point2); + + for (int i = numDivisions + 1; --i >= 0;) + { + *t++ = texturePos; + *t++ = 0.0f; + } + } + + { + GLfloat* v = vertices; + *v++ = centre.getX(); + *v++ = centre.getY(); + + const Point first (grad.point1.translated (0, -sourceRadius) + .transformedBy (transform)); + *v++ = first.getX(); + *v++ = first.getY(); + + for (int i = 1; i < numDivisions; ++i) + { + const float angle = i * (float_Pi * 2.0f / numDivisions); + const Point p (grad.point1.translated (std::sin (angle) * sourceRadius, + std::cos (angle) * -sourceRadius) + .transformedBy (transform)); + *v++ = p.getX(); + *v++ = p.getY(); + } + + *v++ = first.getX(); + *v++ = first.getY(); + } + + target.scissor (rect); + glEnable (GL_TEXTURE_2D); + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glDisableClientState (GL_COLOR_ARRAY); + glDisableClientState (GL_NORMAL_ARRAY); + glVertexPointer (2, GL_FLOAT, 0, vertices); + glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); + setColour (1.0f); + glDrawArrays (GL_TRIANGLE_FAN, 0, numDivisions + 2); + glDisable (GL_SCISSOR_TEST); + } + + void fillRectWithColourGradient (const OpenGLTarget& target, const Rectangle& rect, + const ColourGradient& gradient, const AffineTransform& transform) + { + if (gradient.point1 == gradient.point2) + { + OpenGLHelpers::fillRectWithColour (rect, gradient.getColourAtPosition (1.0)); + } + else + { + const int textureSize = 256; + OpenGLTexture texture; + + HeapBlock lookup (textureSize); + gradient.createLookupTable (lookup, textureSize); + texture.load (lookup, textureSize, 1); + texture.bind(); + + if (gradient.isRadial) + fillWithRadialGradient (target, rect, gradient, transform); + else + fillWithLinearGradient (rect, gradient, transform, textureSize); + } + } + + void fillRectWithFillType (const OpenGLTarget& target, const Rectangle& rect, + const FillType& fill, const bool replaceExistingContents) + { + jassert (! fill.isInvisible()); + jassert (! fill.isColour()); + + if (fill.isGradient()) + { + target.makeActiveFor2D(); + setBlendMode (replaceExistingContents); + + ColourGradient g2 (*(fill.gradient)); + g2.multiplyOpacity (fill.getOpacity()); + + fillRectWithColourGradient (target, rect, g2, fill.transform); + } + else if (fill.isTiledImage()) + { + OpenGLTextureFromImage t (fill.image); + + target.makeActiveFor2D(); + setBlendMode (replaceExistingContents); + + glBindTexture (GL_TEXTURE_2D, t.textureID); + fillRectWithTiledTexture (target, t.width, t.height, rect, + fill.transform, fill.colour.getFloatAlpha()); + glBindTexture (GL_TEXTURE_2D, 0); + } + } +} + +class ClipRegion_Mask; + +//============================================================================== +class ClipRegionBase : public SingleThreadedReferenceCountedObject +{ +public: + ClipRegionBase() noexcept {} + virtual ~ClipRegionBase() {} + + typedef ReferenceCountedObjectPtr Ptr; + + virtual Ptr clone() const = 0; + virtual Ptr applyClipTo (const Ptr& target) = 0; + virtual Ptr clipToRectangle (const Rectangle&) = 0; + virtual Ptr clipToRectangleList (const RectangleList&) = 0; + virtual Ptr excludeClipRectangle (const Rectangle&) = 0; + virtual Ptr clipToPath (const Path& p, const AffineTransform&) = 0; + 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& delta) = 0; + virtual const Rectangle& getClipBounds() const = 0; + virtual void fillAll (const OpenGLTarget&, const FillType& fill, bool replaceContents) = 0; + virtual void fillRect (const OpenGLTarget&, const Rectangle& area, const FillType& fill, bool replaceContents) = 0; + virtual void drawImage (const OpenGLTarget&, const OpenGLTextureFromImage&, float alpha, const Rectangle& targetArea) = 0; +}; + +//============================================================================== +class ClipRegion_Mask : public ClipRegionBase +{ +public: + ClipRegion_Mask (const ClipRegion_Mask& other) + : clip (other.clip), + maskOrigin (other.maskOrigin) + { + const bool ok = mask.initialise (other.mask); + (void) ok; jassert (ok); + } + + explicit ClipRegion_Mask (const Rectangle& r) + : clip (r), + maskOrigin (r.getPosition()) + { + const bool ok = mask.initialise (r.getWidth(), r.getHeight()); + (void) ok; jassert (ok); + mask.clear (Colours::white); + } + + explicit ClipRegion_Mask (const Rectangle& r) + : clip (r.getSmallestIntegerContainer()), + maskOrigin (clip.getPosition()) + { + initialiseClear(); + + glEnableClientState (GL_VERTEX_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + + RenderingHelpers::FloatRectangleRasterisingInfo fr (r); + FillFloatRectCallback callback; + fr.iterate (callback); + } + + explicit ClipRegion_Mask (const EdgeTable& e) + : clip (e.getMaximumBounds()), + maskOrigin (clip.getPosition()) + { + initialiseClear(); + OpenGLHelpers::fillEdgeTable (e, 0, 0, 0); + } + + ClipRegion_Mask (const Rectangle& bounds, const Path& p, const AffineTransform& transform, int oversamplingLevel) + : clip (bounds), maskOrigin (clip.getPosition()) + { + initialiseClear(); + renderPath (p, transform, oversamplingLevel); + } + + static ClipRegion_Mask* createFromPath (Rectangle bounds, const Path& p, const AffineTransform& transform) + { + bounds = bounds.getIntersection (p.getBoundsTransformed (transform).getSmallestIntegerContainer()); + + return bounds.isEmpty() ? nullptr + : new ClipRegion_Mask (bounds, p, transform, (int) defaultOversamplingLevel); + } + + Ptr clone() const { return new ClipRegion_Mask (*this); } + const Rectangle& getClipBounds() const { return clip; } + Ptr applyClipTo (const Ptr& target) { return target->clipToMask (this); } + + void translate (const Point& delta) + { + maskOrigin += delta; + clip += delta; + } + + Ptr clipToRectangle (const Rectangle& r) + { + clip = clip.getIntersection (r); + return clip.isEmpty() ? nullptr : this; + } + + Ptr clipToRectangleList (const RectangleList& r) + { + clip = clip.getIntersection (r.getBounds()); + if (clip.isEmpty()) + return nullptr; + + RectangleList excluded (clip); + + if (excluded.subtract (r)) + { + if (excluded.getNumRectangles() == 1) + return excludeClipRectangle (excluded.getRectangle (0)); + + makeMaskActive(); + glDisable (GL_BLEND); + setColour (0); + fillRectangleList (excluded); + } + + return this; + } + + Ptr excludeClipRectangle (const Rectangle& r) + { + if (r.contains (clip)) + return nullptr; + + makeMaskActive(); + glDisable (GL_BLEND); + setColour (0); + OpenGLHelpers::fillRect (r); + return this; + } + + Ptr clipToPath (const Path& p, const AffineTransform& t) + { + ClipRegion_Mask* tempMask = createFromPath (clip, p, t); + const Ptr tempMaskPtr (tempMask); + return tempMask == nullptr ? nullptr : clipToMask (tempMask); + } + + Ptr clipToEdgeTable (const EdgeTable& et) + { + ClipRegion_Mask* const tempMask = new ClipRegion_Mask (et); + const Ptr tempMaskPtr (tempMask); + return clipToMask (tempMask); + } + + Ptr clipToMask (ClipRegion_Mask* m) + { + jassert (m != nullptr && m != this); + clip = clip.getIntersection (m->clip); + + if (clip.isEmpty()) + return nullptr; + + clipFrameBuffers (OpenGLTarget (mask, maskOrigin), m->mask, m->maskOrigin, true); + return this; + } + + Ptr clipToImageAlpha (const OpenGLTextureFromImage& image, const AffineTransform& transform) + { + makeMaskActive(); + glEnable (GL_BLEND); + glBlendFunc (GL_ZERO, GL_SRC_ALPHA); + glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + fillMaskWithSourceImage (image, transform); + glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + return this; + } + + void fillAll (const OpenGLTarget& target, const FillType& fill, bool replaceContents) + { + jassert (! replaceContents); + fillRectInternal (target, clip, fill, false); + } + + void fillRect (const OpenGLTarget& target, const Rectangle& area, const FillType& fill, bool replaceContents) + { + jassert (! replaceContents); + const Rectangle r (clip.getIntersection (area)); + + if (! r.isEmpty()) + fillRectInternal (target, r, fill, false); + } + + void fillRectInternal (const OpenGLTarget& target, const Rectangle& area, const FillType& fill, bool replaceContents) + { + if (fill.isColour()) + { + target.makeActiveFor2D(); + + setBlendMode (replaceContents); + OpenGLHelpers::setColour (fill.colour); + target.scissor (area); + drawFrameBuffer (mask, maskOrigin); + glDisable (GL_SCISSOR_TEST); + } + else + { + OpenGLFrameBuffer patternBuffer; + bool ok = patternBuffer.initialise (area.getWidth(), area.getHeight()); + (void) ok; jassert (ok); + + fillRectWithFillType (OpenGLTarget (patternBuffer, area.getPosition()), area, fill, true); + clipAndDraw (target, OpenGLTarget (patternBuffer, area.getPosition())); + } + } + + void drawImage (const OpenGLTarget& target, const OpenGLTextureFromImage& source, float alpha, const Rectangle& targetArea) + { + const Rectangle bufferArea (targetArea.getIntersection (clip)); + + if (! bufferArea.isEmpty()) + { + OpenGLFrameBuffer buffer; + bool ok = buffer.initialise (bufferArea.getWidth(), bufferArea.getHeight()); + (void) ok; jassert (ok); + + OpenGLTarget bufferTarget (buffer, bufferArea.getPosition()); + bufferTarget.makeActiveFor2D(); + glDisable (GL_BLEND); + fillRectWithTexture (targetArea, source.textureID, alpha); + + clipAndDraw (target, bufferTarget); + } + } + + void drawImageSelfDestructively (const OpenGLTarget& target, const OpenGLTextureFromImage& source, + float alpha, const AffineTransform& transform) + { + makeMaskActive(); + glEnable (GL_BLEND); + glBlendFunc (GL_DST_ALPHA, GL_ZERO); + fillMaskWithSourceImage (source, transform); + + target.makeActiveFor2D(); + setColour (alpha); + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + drawFrameBuffer (mask, maskOrigin); + } + +private: + OpenGLFrameBuffer mask; + Rectangle clip; + Point maskOrigin; + + void prepareFor2D() const + { + applyFlippedMatrix (maskOrigin.getX(), maskOrigin.getY(), mask.getWidth(), mask.getHeight()); + } + + void makeMaskActive() + { + const bool b = mask.makeCurrentRenderingTarget(); + (void) b; jassert (b); + prepareFor2D(); + } + + void initialiseClear() + { + jassert (! clip.isEmpty()); + bool ok = mask.initialise (clip.getWidth(), clip.getHeight()); + mask.makeCurrentAndClear(); + (void) ok; jassert (ok); + glDisable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + prepareFor2D(); + } + + struct FillFloatRectCallback + { + void operator() (const int x, const int y, const int w, const int h, const int alpha) const + { + 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 }; + glColor4f (1.0f, 1.0f, 1.0f, alpha / 255.0f); + glVertexPointer (2, GL_FLOAT, 0, vertices); + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + } + }; + + void clipAndDraw (const OpenGLTarget& target, const OpenGLTarget& buffer) + { + clipFrameBuffers (buffer, mask, maskOrigin, false); + + target.makeActiveFor2D(); + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + setColour (1.0f); + + drawFrameBuffer (*buffer.frameBuffer, Point (buffer.x, buffer.y)); + } + + void drawFrameBuffer (const OpenGLFrameBuffer& buffer, const Point& topLeft) + { + drawTextureQuad (buffer.getTextureID(), topLeft.getX(), topLeft.getY(), + buffer.getWidth(), buffer.getHeight()); + } + + void fillMaskWithSourceImage (const OpenGLTextureFromImage& image, const AffineTransform& transform) const + { + setColour (1.0f); + glBindTexture (GL_TEXTURE_2D, image.textureID); + 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); + + const GLfloat l = (GLfloat) maskOrigin.getX(); + const GLfloat t = (GLfloat) maskOrigin.getY(); + const GLfloat r = (GLfloat) (maskOrigin.getX() + mask.getWidth()); + const GLfloat b = (GLfloat) (maskOrigin.getY() + mask.getHeight()); + const GLfloat vertices[] = { l, t, r, t, l, b, r, b }; + GLfloat textureCoords[] = { l, t, r, t, l, b, r, b }; + + const AffineTransform inv (transform.inverted().scaled (1.0f / image.width, + 1.0f / image.height)); + + inv.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]); + inv.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]); + + drawTriangleStrip (vertices, textureCoords, 4); + } + + ClipRegion_Mask& operator= (const ClipRegion_Mask&); +}; + + +//============================================================================== +class ClipRegion_Rectangle : public ClipRegionBase +{ +public: + explicit ClipRegion_Rectangle (const Rectangle& r) noexcept + : clip (r) + {} + + Ptr clone() const { return new ClipRegion_Rectangle (clip); } + const Rectangle& getClipBounds() const { return clip; } + Ptr applyClipTo (const Ptr& target) { return target->clipToRectangle (clip); } + void translate (const Point& delta) { clip += delta; } + + Ptr clipToRectangle (const Rectangle& r) + { + clip = clip.getIntersection (r); + return clip.isEmpty() ? nullptr : this; + } + + Ptr clipToRectangleList (const RectangleList& r) + { + if (r.getNumRectangles() <= 1) + return clipToRectangle (r.getRectangle (0)); + + if (r.containsRectangle (clip)) + return this; + + return toMask()->clipToRectangleList (r); + } + + Ptr excludeClipRectangle (const Rectangle& r) + { + return r.contains (clip) ? nullptr + : toMask()->excludeClipRectangle (r); + } + + Ptr clipToMask (ClipRegion_Mask* m) { return m->clipToRectangle (clip); } + Ptr clipToPath (const Path& p, const AffineTransform& transform) { return toMask()->clipToPath (p, transform); } + Ptr clipToEdgeTable (const EdgeTable& et) { return toMask()->clipToEdgeTable (et); } + Ptr clipToImageAlpha (const OpenGLTextureFromImage& image, const AffineTransform& transform) { return toMask()->clipToImageAlpha (image, transform); } + + void fillAll (const OpenGLTarget& target, const FillType& fill, bool replaceContents) + { + fillRectInternal (target, clip, fill, replaceContents); + } + + void fillRect (const OpenGLTarget& target, const Rectangle& area, const FillType& fill, bool replaceContents) + { + const Rectangle r (clip.getIntersection (area)); + + if (! r.isEmpty()) + fillRectInternal (target, r, fill, replaceContents); + } + + void drawImage (const OpenGLTarget& target, const OpenGLTextureFromImage& source, float alpha, const Rectangle& targetArea) + { + target.makeActiveFor2D(); + target.scissor (clip); + setNormalBlendingMode(); + fillRectWithTexture (targetArea, source.textureID, alpha); + glDisable (GL_SCISSOR_TEST); + } + +private: + Rectangle clip; + + void fillRectInternal (const OpenGLTarget& target, const Rectangle& area, const FillType& fill, bool replaceContents) + { + if (fill.isColour()) + { + target.makeActiveFor2D(); + setBlendMode (replaceContents); + glDisable (GL_TEXTURE_2D); + OpenGLHelpers::fillRectWithColour (area, fill.colour); + } + else + { + fillRectWithFillType (target, area, fill, replaceContents); + } + } + + Ptr toMask() const + { + return new ClipRegion_Mask (clip); + } + + ClipRegion_Rectangle& operator= (const ClipRegion_Rectangle&); +}; + + +//============================================================================== +class OpenGLRenderer::SavedState +{ +public: + SavedState (const OpenGLTarget& target_) + : clip (new ClipRegion_Rectangle (Rectangle (target_.width, target_.height))), + transform (0, 0), interpolationQuality (Graphics::mediumResamplingQuality), + target (target_), transparencyLayerAlpha (1.0f) + { + } + + SavedState (const SavedState& other) + : clip (other.clip), transform (other.transform), font (other.font), + fillType (other.fillType), interpolationQuality (other.interpolationQuality), + target (other.target), transparencyLayerAlpha (other.transparencyLayerAlpha), + transparencyLayer (other.transparencyLayer) + { + } + + bool clipToRectangle (const Rectangle& r) + { + if (clip != nullptr) + { + if (transform.isOnlyTranslated) + { + cloneClipIfMultiplyReferenced(); + clip = clip->clipToRectangle (transform.translated (r)); + } + else + { + Path p; + p.addRectangle (r); + clipToPath (p, AffineTransform::identity); + } + } + + return clip != nullptr; + } + + bool clipToRectangleList (const RectangleList& r) + { + if (clip != nullptr) + { + if (transform.isOnlyTranslated) + { + cloneClipIfMultiplyReferenced(); + RectangleList offsetList (r); + offsetList.offsetAll (transform.xOffset, transform.yOffset); + clip = clip->clipToRectangleList (offsetList); + } + else + { + clipToPath (r.toPath(), AffineTransform::identity); + } + } + + return clip != nullptr; + } + + bool excludeClipRectangle (const Rectangle& r) + { + if (clip != nullptr) + { + cloneClipIfMultiplyReferenced(); + + if (transform.isOnlyTranslated) + { + clip = clip->excludeClipRectangle (transform.translated (r)); + } + else + { + Path p; + p.addRectangle (r.toFloat()); + p.applyTransform (transform.complexTransform); + p.addRectangle (clip->getClipBounds().toFloat()); + p.setUsingNonZeroWinding (false); + clip = clip->clipToPath (p, AffineTransform::identity); + } + } + + return clip != nullptr; + } + + void clipToPath (const Path& p, const AffineTransform& t) + { + if (clip != nullptr) + { + cloneClipIfMultiplyReferenced(); + clip = clip->clipToPath (p, transform.getTransformWith (t)); + } + } + + void clipToImageAlpha (const Image& sourceImage, const AffineTransform& t) + { + if (clip != nullptr) + { + Path p; + p.addRectangle (sourceImage.getBounds()); + clipToPath (p, t); + + if (sourceImage.hasAlphaChannel() && clip != nullptr) + { + cloneClipIfMultiplyReferenced(); + clip = clip->clipToImageAlpha (sourceImage, transform.getTransformWith (t)); + } + } + } + + bool clipRegionIntersects (const Rectangle& r) const + { + return clip != nullptr + && (transform.isOnlyTranslated ? clip->getClipBounds().intersects (transform.translated (r)) + : getClipBounds().intersects (r)); + } + + Rectangle getClipBounds() const + { + return clip != nullptr ? transform.deviceSpaceToUserSpace (clip->getClipBounds()) + : Rectangle(); + } + + SavedState* beginTransparencyLayer (float opacity) + { + SavedState* s = new SavedState (*this); + + if (clip != nullptr) + { + const Rectangle& clipBounds = clip->getClipBounds(); + + OpenGLFrameBufferImage* fbi = new OpenGLFrameBufferImage (clipBounds.getWidth(), clipBounds.getHeight()); + fbi->frameBuffer.clear (Colours::transparentBlack); + s->transparencyLayer = Image (fbi); + s->target = OpenGLTarget (fbi->frameBuffer, Point()); + s->transparencyLayerAlpha = opacity; + s->transform.moveOriginInDeviceSpace (-clipBounds.getX(), -clipBounds.getY()); + s->cloneClipIfMultiplyReferenced(); + s->clip->translate (-clipBounds.getPosition()); + } + + return s; + } + + void endTransparencyLayer (SavedState& finishedLayerState) + { + if (clip != nullptr) + clip->drawImage (target, finishedLayerState.transparencyLayer, + finishedLayerState.transparencyLayerAlpha, clip->getClipBounds()); + } + + //============================================================================== + void fillRect (const Rectangle& r, const bool replaceContents) + { + if (clip != nullptr) + { + if (transform.isOnlyTranslated) + { + clip->fillRect (target, r.translated (transform.xOffset, transform.yOffset), + getFillType(), replaceContents); + } + else + { + Path p; + p.addRectangle (r); + fillPath (p, AffineTransform::identity); + } + } + } + + void fillRect (const Rectangle& r) + { + if (clip != nullptr) + { + if (transform.isOnlyTranslated) + { + fillShape (new ClipRegion_Mask (r.translated ((float) transform.xOffset, + (float) transform.yOffset)), false); + } + else + { + Path p; + p.addRectangle (r); + fillPath (p, AffineTransform::identity); + } + } + } + + void fillPath (const Path& path, const AffineTransform& t) + { + if (clip != nullptr) + { + ClipRegion_Mask* m = ClipRegion_Mask::createFromPath (clip->getClipBounds(), path, + transform.getTransformWith (t)); + + if (m != nullptr) + fillShape (m, false); + } + } + + void drawGlyph (int glyphNumber, const AffineTransform& t) + { + if (clip != nullptr) + { + const float fontHeight = font.getHeight(); + + const ScopedPointer et (font.getTypeface()->getEdgeTableForGlyph + (glyphNumber, transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + .followedBy (t)))); + + if (et != nullptr) + fillShape (new ClipRegion_Mask (*et), false); + } + } + + void drawLine (const Line & line) + { + Path p; + p.addLineSegment (line, 1.0f); + fillPath (p, AffineTransform::identity); + } + + void fillShape (ClipRegionBase::Ptr shapeToFill, const bool replaceContents) + { + jassert (clip != nullptr && shapeToFill != nullptr); + + if (! fillType.isInvisible()) + { + shapeToFill = clip->applyClipTo (shapeToFill); + + if (shapeToFill != nullptr) + shapeToFill->fillAll (target, getFillType(), replaceContents); + } + } + + //============================================================================== + void drawImage (const Image& image, const AffineTransform& trans) + { + if (clip == nullptr || fillType.colour.isTransparent()) + return; + + const AffineTransform t (transform.getTransformWith (trans)); + const float alpha = fillType.colour.getFloatAlpha(); + + if (t.isOnlyTranslation()) + { + int tx = (int) (t.getTranslationX() * 256.0f); + int ty = (int) (t.getTranslationY() * 256.0f); + + if (((tx | ty) & 0xf8) == 0) + { + tx = ((tx + 128) >> 8); + ty = ((ty + 128) >> 8); + + clip->drawImage (target, image, alpha, Rectangle (tx, ty, image.getWidth(), image.getHeight())); + return; + } + } + + if (t.isSingularity()) + return; + + Path p; + p.addRectangle (image.getBounds()); + ClipRegion_Mask* m = ClipRegion_Mask::createFromPath (clip->getClipBounds(), p, t); + + if (m != nullptr) + { + ClipRegionBase::Ptr c (clip->applyClipTo (m)); + + if (c != nullptr) + { + m = dynamic_cast (c.getObject()); + + jassert (m != nullptr); + m->drawImageSelfDestructively (target, image, alpha, t); + } + } + } + + //============================================================================== + ClipRegionBase::Ptr clip; + RenderingHelpers::TranslationOrTransform transform; + Font font; + FillType fillType; + Graphics::ResamplingQuality interpolationQuality; + +private: + OpenGLTarget target; + float transparencyLayerAlpha; + Image transparencyLayer; + + void cloneClipIfMultiplyReferenced() + { + if (clip->getReferenceCount() > 1) + clip = clip->clone(); + } + + FillType getFillType() const + { + return fillType.transformed (transform.getTransform()); + } + + SavedState& operator= (const SavedState&); +}; + + +//============================================================================== +OpenGLRenderer::OpenGLRenderer (OpenGLComponent& target) + : stack (new SavedState (OpenGLTarget (target.getFrameBufferID(), target.getWidth(), target.getHeight()))) +{ + target.makeCurrentRenderingTarget(); +} + +OpenGLRenderer::OpenGLRenderer (OpenGLFrameBuffer& target) + : stack (new SavedState (OpenGLTarget (target, Point()))) +{ + // 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; } +void OpenGLRenderer::setOrigin (int x, int y) { stack->transform.setOrigin (x, y); } +void OpenGLRenderer::addTransform (const AffineTransform& t) { stack->transform.addTransform (t); } +float OpenGLRenderer::getScaleFactor() { return stack->transform.getScaleFactor(); } +Rectangle OpenGLRenderer::getClipBounds() const { return stack->getClipBounds(); } +bool OpenGLRenderer::isClipEmpty() const { return stack->clip == nullptr; } +bool OpenGLRenderer::clipRegionIntersects (const Rectangle& r) { return stack->clipRegionIntersects (r); } +bool OpenGLRenderer::clipToRectangle (const Rectangle& r) { return stack->clipToRectangle (r); } +bool OpenGLRenderer::clipToRectangleList (const RectangleList& r) { return stack->clipToRectangleList (r); } +void OpenGLRenderer::excludeClipRectangle (const Rectangle& r) { stack->excludeClipRectangle (r); } +void OpenGLRenderer::clipToPath (const Path& path, const AffineTransform& t) { stack->clipToPath (path, t); } +void OpenGLRenderer::clipToImageAlpha (const Image& im, const AffineTransform& t) { stack->clipToImageAlpha (im, t); } +void OpenGLRenderer::saveState() { stack.save(); } +void OpenGLRenderer::restoreState() { stack.restore(); } +void OpenGLRenderer::beginTransparencyLayer (float opacity) { stack.beginTransparencyLayer (opacity); } +void OpenGLRenderer::endTransparencyLayer() { stack.endTransparencyLayer(); } +void OpenGLRenderer::setFill (const FillType& fillType) { stack->fillType = fillType; } +void OpenGLRenderer::setOpacity (float newOpacity) { stack->fillType.setOpacity (newOpacity); } +void OpenGLRenderer::setInterpolationQuality (Graphics::ResamplingQuality quality) { stack->interpolationQuality = quality; } +void OpenGLRenderer::fillRect (const Rectangle& r, bool replace) { stack->fillRect (r, replace); } +void OpenGLRenderer::fillPath (const Path& path, const AffineTransform& t) { stack->fillPath (path, t); } +void OpenGLRenderer::drawImage (const Image& im, const AffineTransform& t) { stack->drawImage (im, t); } +void OpenGLRenderer::drawVerticalLine (int x, float top, float bottom) { stack->fillRect (Rectangle ((float) x, top, 1.0f, bottom - top)); } +void OpenGLRenderer::drawHorizontalLine (int y, float left, float right) { stack->fillRect (Rectangle (left, (float) y, right - left, 1.0f)); } +void OpenGLRenderer::drawGlyph (int glyphNumber, const AffineTransform& t) { stack->drawGlyph (glyphNumber, t); } +void OpenGLRenderer::drawLine (const Line & line) { stack->drawLine (line); } +void OpenGLRenderer::setFont (const Font& newFont) { stack->font = newFont; } +Font OpenGLRenderer::getFont() { return stack->font; } + +END_JUCE_NAMESPACE diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h new file mode 100644 index 0000000000..d7d796e620 --- /dev/null +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h @@ -0,0 +1,83 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__ +#define __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__ + + +//============================================================================== +/** A LowLevelGraphicsContext for rendering into an OpenGL framebuffer or window. +*/ +class JUCE_API OpenGLRenderer : public LowLevelGraphicsContext +{ +public: + explicit OpenGLRenderer (OpenGLComponent& target); + explicit OpenGLRenderer (OpenGLFrameBuffer& target); + ~OpenGLRenderer(); + + bool isVectorDevice() const; + void setOrigin (int x, int y); + void addTransform (const AffineTransform&); + float getScaleFactor(); + bool clipToRectangle (const Rectangle&); + bool clipToRectangleList (const RectangleList&); + void excludeClipRectangle (const Rectangle&); + void clipToPath (const Path& path, const AffineTransform&); + void clipToImageAlpha (const Image& sourceImage, const AffineTransform&); + bool clipRegionIntersects (const Rectangle&); + Rectangle getClipBounds() const; + bool isClipEmpty() const; + + void saveState(); + void restoreState(); + + void beginTransparencyLayer (float opacity); + void endTransparencyLayer(); + + void setFill (const FillType& fillType); + void setOpacity (float newOpacity); + void setInterpolationQuality (Graphics::ResamplingQuality); + + void fillRect (const Rectangle& r, bool replaceExistingContents); + void fillPath (const Path& path, const AffineTransform& transform); + void drawImage (const Image& sourceImage, const AffineTransform& transform); + void drawLine (const Line & line); + void drawVerticalLine (int x, float top, float bottom); + void drawHorizontalLine (int y, float left, float right); + + void setFont (const Font&); + Font getFont(); + + void drawGlyph (int glyphNumber, const AffineTransform&); + + #ifndef DOXYGEN + class SavedState; + #endif + +private: + RenderingHelpers::SavedStateStack stack; +}; + +#endif // __JUCE_OPENGLGRAPHICSCONTEXT_JUCEHEADER__ diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp index b2f8ad6afd..923595ca47 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp @@ -35,13 +35,11 @@ void* OpenGLHelpers::getExtensionFunction (const char* functionName) { #if JUCE_WINDOWS return (void*) wglGetProcAddress (functionName); - - #elif JUCE_MAC - static void* handle = dlopen (nullptr, RTLD_LAZY); - return dlsym (handle, functionName); - #elif JUCE_LINUX return (void*) glXGetProcAddress ((const GLubyte*) functionName); + #else + static void* handle = dlopen (nullptr, RTLD_LAZY); + return dlsym (handle, functionName); #endif } diff --git a/modules/juce_opengl/opengl/juce_OpenGLImage.cpp b/modules/juce_opengl/opengl/juce_OpenGLImage.cpp index 4c7cdd14c3..e90ac5e6c5 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLImage.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLImage.cpp @@ -38,7 +38,7 @@ OpenGLFrameBufferImage::~OpenGLFrameBufferImage() {} LowLevelGraphicsContext* OpenGLFrameBufferImage::createLowLevelContext() { - return new LowLevelGraphicsSoftwareRenderer (Image (this)); + return new OpenGLRenderer (frameBuffer); } Image::SharedImage* OpenGLFrameBufferImage::clone() @@ -75,7 +75,24 @@ namespace OpenGLImageHelpers static void read (OpenGLFrameBuffer& frameBuffer, Image::BitmapData& bitmapData, int x, int y) { frameBuffer.readPixels ((PixelARGB*) bitmapData.data, - Rectangle (x, y, bitmapData.width, bitmapData.height)); + Rectangle (x, frameBuffer.getHeight() - (y + bitmapData.height), bitmapData.width, bitmapData.height)); + + verticalRowFlip ((PixelARGB*) bitmapData.data, bitmapData.width, bitmapData.height); + } + + static void verticalRowFlip (PixelARGB* const data, const int w, const int h) + { + HeapBlock tempRow (w); + const int rowSize = sizeof (PixelARGB) * w; + + for (int y = 0; y < h / 2; ++y) + { + PixelARGB* const row1 = data + y * w; + PixelARGB* const row2 = data + (h - 1 - y) * w; + memcpy (tempRow, row1, rowSize); + memcpy (row1, row2, rowSize); + memcpy (row2, tempRow, rowSize); + } } }; @@ -87,7 +104,14 @@ namespace OpenGLImageHelpers void write (const PixelARGB* const data) const noexcept { - frameBuffer.writePixels (data, area); + HeapBlock invertedCopy (area.getWidth() * area.getHeight()); + const int rowSize = sizeof (PixelARGB) * area.getWidth(); + + for (int y = 0; y < area.getHeight(); ++y) + memcpy (invertedCopy + area.getWidth() * y, + data + area.getWidth() * (area.getHeight() - 1 - y), rowSize); + + frameBuffer.writePixels (invertedCopy, area); } OpenGLFrameBuffer& frameBuffer;