aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp
Commit message (Collapse)AuthorAgeFilesLines
* Bug 801: VBAA Render-Mode Based on SampleCount (not a user-based texWidth) ; ↵Sven Gothel2014-03-014-32/+104
| | | | | | | | | | | | | | Proper FontSize -> PixelSize VBAA Render-Mode Based on SampleCount (not a user-based texWidth) - All Region based APIs now use 'sampleCount' instead of 'texWidth' - VBORegion2PES2 calculates perspective FBO width/height considering the sampleCount Proper FontSize -> PixelSize - Font: Add getPixelSize(fontSize, dpi) - Text* Demos/Classes: Use proper fontSize -> PixelSize
* Bug 801: Drop TypecastRenderer's CUBIC mode if p3 is 'looped'Sven Gothel2014-02-281-2/+2
|
* Bug 801: TypecastRenderer: Rename local point vars for better reviewSven Gothel2014-02-281-50/+51
|
* Bug 801: TypecastRenderer: Disable DEBUG ; Performance Note: ~800-1200 fps ↵Sven Gothel2014-02-281-1/+1
| | | | | | | | | on uncached text line Performance Note: ~800-1200 fps on uncached text line Compared to c3621221b9a563495b4f54fe60e18e8db8cc57fb: ~600 fps and previous impl. ~60fps.
* Bug 801: Fix TypecastRenderer End-Of-Contour and Shape-Closing; add cubic pathSven Gothel2014-02-281-46/+81
| | | | | | | | | | | | | | | | | | | | | | | - Fix TypecastRenderer End-Of-Contour (EOC) - Iterate through contour block up-until EOC-1, not trying to create a new 'path' from EOC. - Add cubic path - Detect a cubic path and use it, i.e. on-off-off-on - Fix Shape-Closing - Close shape at head, not tail, since we add vertices from the head. - Misc - addShape*(..) uses Point parameter 'onCurve' field reflecting proper handling. Status: Ubuntu Font: No artifacts Lucida: Removed all artifacts, but for character 'M' !? - No odd MID point - Maybe inside-outside (inner) detection is buggy ?
* Bug 801: TextRegionUtil add 'special' for cache-key; Minor editsSven Gothel2014-02-284-4/+8
| | | | | | Minor edits: - Add some docs to curve-shader and remove FIXME remark about gcu_Alpha, which will be used < 1.0. - Font: Add more TTF references
* Bug 801: Outline.setClosed(boolean [closed->closeTail]): Always close, but ↵Sven Gothel2014-02-281-12/+8
| | | | allow to either close-tail or head; OutlineShape/Triangulator: Pass 'sharpness' (very little effect though)
* Bug 801: Graph TextRenderer Cleanup Part-6: Fix TypecastRenderer; Minor EditingSven Gothel2014-02-283-63/+89
| | | | | | | Fix TypecastRenderer: - Ensure quad shapes are closed! - Revalidate point -> shape interpretation using orig. Typcast code - Fix 'midPoint(..)' use float values
* Bug 801: Graph TextRenderer Cleanup Part-5: *Region API Cleanup (protected ↵Sven Gothel2014-02-272-16/+10
| | | | impl. part)
* Bug 801: Graph TextRenderer Cleanup Part-4: Text[Render->Region]Util API: ↵Sven Gothel2014-02-271-20/+23
| | | | Better separation of cached and uncached regions
* Bug 801: Graph TextRenderer Cleanup Part-3: Region.addOutlineShape(..) Push ↵Sven Gothel2014-02-273-126/+115
| | | | | | | | | | | | | | | | | | GL data directly incl. all index validations Region: - Remove redundant methods to make OutlineShape the unique source. - addVertex(..) - addTriangles(..) - Perform all index validations in addOutlineShape(..) - Push OutlineShape's vertex data and it's triangle indices directly to VBO. GLRegion: Add clear(..) method, allowing to clear the region for new data, i.e. OutlineShapes
* Bug 801: Graph TextRenderer Cleanup Part-2: Remove Path2D from ↵Sven Gothel2014-02-275-349/+49
| | | | | | | | | Glyph/Typecast* ; Misc Cleanup Commit c3621221b9a563495b4f54fe60e18e8db8cc57fb introduced create an OutlineShape per Glyph from it's data w/o going through Path2D. Misc Cleanup: Remove unused code/fields, use private/final where possible.
* Merge branch 'master' into 2.2-trainSven Gothel2014-02-261-2/+2
|\
| * Bug 984 - Fix GLBufferObjectTracker.mapBuffer(..)'s mapBufferImpl(..) ↵Sven Gothel2014-02-261-2/+2
| | | | | | | | | | | | | | | | | | parameters for mapBufferRange(..) and mapNamedBufferRange(..) GLBufferObjectTracker.mapBuffer(..) variant for mapBufferRange(..) and mapNamedBufferRange(..) used wrong parameters in it's mapBufferImpl(..) call. Fixed and added mapBufferRange(..) test in TestMapBufferRead01NEWT
* | Bug 802: Graph TextRenderer Performance Part-2 (fix artifacts, cleanup, ↵Sven Gothel2014-02-254-149/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | incomplete) - OutlineShape - Add DIRTY_VERTICES bit in triangulation, which in turn solves the rendering artifact issue. - transformOutlines(..) -> protected - Note: Always pick triangles first, then vertices. The former renders vertices dirty. - Region - Make triangles / vertices accessible - Add 'validateIndices()' to add indices for triangles, code moved from the GLRegion* impl. Shall be refined later! - GLRegion - Passing 'RegionRenderer' instead of RenderState .. reducing argument numbers and aligning all related 'render' methods while giving association to the RegionRenderer. - Renderer -> RegionRenderer, dropping 'intermediate' RegionRenderer - Dropping draw() in RegionRenderer, should be issued simply by GLRegion in a unique fashion. - Dropping RegionFactory Too simple code as-is, simply invoke in Region.create(..) - Overall: - Add 'final' qualifier - Remove overloaded methods where rither default args can be used or a followup method call completes the 'intention'.
* | Merge branch 'master' into 2.2-trainSven Gothel2014-02-251-2/+2
|\|
| * Bug 927: Try fix deadlock.Xerxes Rånby2014-02-251-2/+2
| | | | | | | | | | | | (14:15:13) sgothel: @Xerxes: In doResume .. do a 'while( !isActive && !shallPause && isRunning ) {' (14:15:52) sgothel: doPause: while( isActive && !shallPause && isRunning ) (14:31:55) sgothel: doPause only: while( isActive && isRunning ) {
* | Bug 802: Graph TextRenderer Performance Part-1 (incomplete, rendering artifacts)Sven Gothel2014-02-2412-544/+226
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Strategy Change: - Font.Glyph itself holds it's OutlineShape with it's default scaling. Triangulation is done only once per glyph! - A CharSequence produces a Region by translating and scaling each Glyphs's OutlineShape. This removes the need for re-triangulate - see above. See: TextRendererUtil - The indices of re-added Triangles are offset to the new vertices (FIXME, seems not be be accurate yet). - OutlineShape's vertices and triangles are reused if 'clean'. - Simplified code - Reduced copies API Changes: - OutlineShape, Region, ...: See above - Removed TextRenderer, GlyphShape and GlyphString: Redundant - Added TextRendererUtil to produce the Region from CharSequence Result: - Over 600 fps while changing text for each frame. Previously only ~60fps max. TODO: - Region shall not hold the triangles itself, but the indices instead. This will remove the need to swizzle w/ vertices in the Region Renderer impl and easies reusage of OutlineShapes.
* | Merge branch 'master' into stash_glyphcacheSven Gothel2014-02-23405-13482/+28242
|\| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: make/scripts/tests.sh src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java src/jogl/classes/com/jogamp/graph/curve/Region.java src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java src/jogl/classes/com/jogamp/graph/font/Font.java src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java src/jogl/classes/jogamp/graph/curve/text/GlyphString.java src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
| * ALAudioSink: Add thread-name to exceptions; stopImpl shall not throw an ↵Sven Gothel2014-02-221-22/+38
| | | | | | | | exception at destroy
| * Bug 927 - Multithreading (MT) issues ALAudioSinkSven Gothel2014-02-221-53/+54
| | | | | | | | | | | | | | Add global synchronization around ALAudioSink constructor code, which 'magically' solves the openal-soft multithreading issues .. This is a workaround.
| * Bug 927 - Multithreading (MT) issues libav/ffmpegSven Gothel2014-02-224-13/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | FFMPEG Natives: - Move 'mutex_avcodec_openclose' to local static and initialize at initSymbols0 - setStream0: - Add another locked mutex block around: - [ sp_avformat_open_input .. sp_avformat_find_stream_info ] This solves the issue of: [NULL @ 0x89d20c60] insufficient thread locking around avcodec_open/close()
| * Match Bitstream changes of gluegen commit ↵Sven Gothel2014-02-211-35/+35
| | | | | | | | 4447232af0d95a4348d09d4ed03fbef48394ca3a
| * Bug 980: Use Bitsream class for JPEGDecoderSven Gothel2014-02-201-69/+32
| |
| * GLContextImpl/GLDrawableImpl.getDefaultReadBuffer(..): Pass hint whether ↵Sven Gothel2014-02-183-4/+6
| | | | | | | | dedicated read-drawable is being used (double buffering)
| * Bug 927: Fix minor MT issues w/ libav/ffmpegSven Gothel2014-02-164-70/+76
| | | | | | | | | | | | | | | | | | | | | | | | | | Issue: [NULL @ 0x35bde60] insufficient thread locking around avcodec_open/close() Decorating said libav functions w/ mutex lock/release. Abstract impl. to either use pthread or JNI Monitor, but using the latter to reduce dependencies (ming64 windows). FFMPEGNatives is now an abstract class containing the 'static final Object mutex_avcodec_openclose'
| * Graph: RendereState: Create own PMVMatrix if passed value is null; Renderer: ↵Sven Gothel2014-02-151-4/+0
| | | | | | | | Add reshapeNotify(..) for NOP PMV reshape notification
| * Bug 927 - Multithreading (MT) issues with ALAudioSink (openal-soft)Sven Gothel2014-02-151-31/+102
| | | | | | | | | | | | | | | | | | | | | | | | | | | | - Using update openal-soft (commit 7297c3214a4c648aaee81a9877da15b88f798197) - Analyzed openal-soft threading issues: - a global-lock would have removed the issue - turns out that using ALC_EXT_thread_local_context's alcSetThreadContext(..) instead of alcMakeContextCurrent(..) solves the issue - Cleaned up al*GetError() queries and handling - Simplified flush/dequeue buffers
| * GLPixelStorageModes: Safe and restore GL2ES3 modes, i.e. add missing GLES3 ↵Sven Gothel2014-02-141-8/+8
| | | | | | | | modes. GLStateTracker: Use proper GL names for enums
| * Bug 972 - Reduce ClassLoader Lookup, i.e. Class.forName(..): GLProfile, ↵Sven Gothel2014-02-121-7/+5
| | | | | | | | | | | | | | | | | | | | | | | | GLContextImpl, DisplayImpl GLProfile, GLContextImpl: - ReflectionUtil.DEBUG_STATS_FORNAME: Dump forName stats if set - Cache GL*Impl and GL*ProcAddressTable Constructor<?> for GLContextImpl's createInstance(..) - Remove off-thread early classloading thread which only adds complications DisplayImpl: - Remove one redundant availability test
| * GLMediaPlayer: Add user attached objects, similar to GLContext - Allowing ↵Sven Gothel2014-01-261-0/+19
| | | | | | | | GLMediaEventListener impl. to access GLMediaPlayer associated objects
| * Bug 948 - Autodetect GLRendererQuirks.SingletonEGLDisplayOnlySven Gothel2014-01-242-22/+17
| | | | | | | | | | | | | | | | | | Refines commit fbe00e6f5dca8043b40dd96f096fecc9424e0cc3 Instead of querying driver artifacts (vendor, platform, version ..) we simply can autodetect this quirk by trying to get a second egl-display handle when initializing the EGLDrawablFactory's default device: EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY)
| * Bug 948 - NVIDIA 331.38 (Linux X11) EGL impl. only supports _one_ EGL ↵Sven Gothel2014-01-243-89/+167
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Display via eglGetDisplay(..) NVIDIA 331.38 (Linux X11) EGL impl. only supports _one_ EGL Display via eglGetDisplay. - Subsequent eglGetDisplay(..) calls fail. - Using the same 'global' egl-display does work though Remedy: Add 'GLRendererQuirks.SingletonEGLDisplayOnly' Detection of quirk is done as usual in GLContextImpl.setRendererQuirks(..), and EGLDrawableFactory passes the quirk, if detected, down to EGLDisplayUtil. The latter implements the singleton eglDisplay handle. EGLDisplayUtil: Cleaned up .. - EGLDisplayRef employs the reference handling incl. eglInitialize(..) and eglTerminate(), as well as the new singleton quirk. - Mark all internal methods 'private', to remove possible [untested] sideffects.
| * Bug 950 - Recognize full FBO capabilities for ES 3.0 - ↵Sven Gothel2014-01-241-1/+1
| | | | | | | | | | | | | | | | [GLContext|GL].hasFullFBOSupport() == true OpenGL ES 3.0 supports full framebuffer operations, incl. multiple color-attachments and multisample. Hence [GLContext|GL].hasFullFBOSupport() shall returns true w/ a ES 3.0 context.
| * EGLDisplayUtil.eglCreateEGLGraphicsDevice(..): Don't open() device implicit; ↵Sven Gothel2014-01-235-42/+52
| | | | | | | | EGLDrawableFactory.mapAvailableEGLESConfig(..): Clarify
| * GLBufferObjectTracker: Fix copyright notice (drop Sun Microsystems since ↵Sven Gothel2014-01-211-33/+21
| | | | | | | | this is a rewrite of previous GLBufferSizeTracker)
| * Better shared GLAutoDrawable synchronization: Block slave instances to also ↵Sven Gothel2014-01-212-1/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | block until all master's GLEventListener.init(..) methods have been called Better shared GLAutoDrawable synchronization. Block slave instances to also block until all master's GLEventListener.init(..) methods have been called - GLSharedContextSetter: Add areAllGLEventListenerInitialized() - GLCanvas (SWT, AWT) - GLJPanel - GLAutoDrawableBase (GLWindow, ..) - GLDrawableHelper's isSharedGLContextPending(..) takes 'areAllGLEventListenerInitialized()' into consideration allowing to block the slave creation until master is completed. This solves teh use case, where the master creates resources in it's GLEventListener initialization (buffers), which are shared with it's slaves.
| * Bug 942: GLBufferObjectTracker: Tracking GLBufferStorage accurately, ↵Sven Gothel2014-01-216-273/+650
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | synchronized and secure [1/2] GLBufferSizeTracker becomes GLBufferObjectTracker and tracks the buffer's data store, GLBufferStorage, accurately, synchronized and secure. Synchronization is required, since the GLBufferStorage can be shared across many GLContext on multiple threads. This requires all GLBufferStorage lifecycle affecting GL functions to utilize synchronized GLBufferObjectTracker methods while passing a native GL-func callback. These GL functions are: - glBufferData, glBufferStorage (GL 4.4), glNamedBufferDataEXT Creating the GLBufferStorage object - glMapBuffer, glMapBufferRange, and their *Named*EXT variants - glUnmapBuffer, glUnmapNamedBufferEXT 'glDeleteBuffers' can simply notify the GLBufferObjectTracker No more HashMap is required to associate the mapped buffer address to the mapped ByteBuffer. GLBufferObjectTracker simply utilizes a buffer-name (int) -> GLBufferStorage map. +++ The security aspect shall be implemented by validating all arguments whether they match the required GL constraints, as well as validating tracked states like 'size'. The following functions will throw an GLException accordingly: - glBufferData, glNamedBufferDataEXT * @throws GLException if size is less-than zero * @throws GLException if a native GL-Error occurs - glBufferStorage (GL 4.4) * @throws GLException if size is less-or-eqaul zero * @throws GLException if a native GL-Error occurs - glMapBuffer, and it's *Named*EXT variant * @throws GLException if buffer is not bound to target * @throws GLException if buffer is not tracked * @throws GLException if buffer is already mapped * @throws GLException if buffer has invalid store size, i.e. less-than zero - glMapBufferRange, and it's *Named*EXT variant * @throws GLException if buffer is not bound to target * @throws GLException if buffer is not tracked * @throws GLException if buffer is already mapped * @throws GLException if buffer has invalid store size, i.e. less-than zero * @throws GLException if buffer mapping range does not fit, incl. offset - glMapBufferRange, and it's *Named*EXT variant Only clear mapped buffer reference of GLBufferStorage if native unmap was successful. Further more special error handling shall be applied to: - glMapBuffer, and it's *Named*EXT variant, glMapBuffer, and it's *Named*EXT variant - A zero GLBufferStorage size will avoid a native call and returns null - A null native mapping result indicating an error will not cause a GLException but returns null This allows the user to handle this case.
| * Bug 943 - GLBufferStateTracker shall support tracking all possible buffer ↵Sven Gothel2014-01-151-12/+27
| | | | | | | | targets
| * Bug 942: Bug 942 - Review GLBuffer[State|Size]Tracker and NIO mapped buffersSven Gothel2014-01-144-92/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit f8a74c9831c65725a699320c27e62161a0378241 reverted commit 7c5483d5b20aed9c87c5ce3f6bc840b6546edcd1 due to the fact that the buffer binding itself is _not_ shared across shared GLContext! Apply uncritical changes of 7c5483d5b20aed9c87c5ce3f6bc840b6546edcd1: +++ Simplify GLBufferSizeTracker creation @ GLContextImpl ctor, make it final. +++ Clear the GLBufferSizeTracker (@destruction) only if no more created shares are left! +++ Refine API doc. +++
| * Revert "Bug 942 - Share GLBufferStateTracker ; Unify GLBufferStateTracker ↵Sven Gothel2014-01-144-187/+260
| | | | | | | | | | | | and GLBufferSizeTracker (simplification)" This reverts commit 7c5483d5b20aed9c87c5ce3f6bc840b6546edcd1.
| * Bug 942 - Share GLBufferStateTracker ; Unify GLBufferStateTracker and ↵Sven Gothel2014-01-144-260/+187
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | GLBufferSizeTracker (simplification) Due to future mapped buffer tracking, the GLBufferStateTracker instance shall be shared across shared GLContextImpl instances similar to GLSizeStateTracker! This allows us to merge GLSizeStateTracker code into GLBufferStateTracker to simplify the implementation. +++ Clear the GLBufferStateTracker (@destruction) only if no more created shares are left! +++
| * Bug 938 - MemoryObject.java has no more equals() methodSven Gothel2014-01-141-6/+22
| | | | | | | | | | | | Re-adding 'equals(..)' method erroneously removed with commit 8457bf35fee253d9af29ff1150a9671f6896fc17. 'equals(..)' is important to allow the HashMap<> for glMapBuffer(..) work properly!
| * Fix GLDrawableHelper.resizeOffscreenDrawable(..): Do nothing if ↵Sven Gothel2014-01-111-4/+7
| | | | | | | | | | | | | | | | !drawable.isRealized() - similar to it's recreateDrawable() and test only _after_ having the surface lock! Only after the surface lock we are thread safe. In case drawable has been pulled, do nothing ..
| * Misc Cleanup: JAWTWindow: Reusing visible in HIERARCHY listener; Remove ↵Sven Gothel2014-01-112-7/+7
| | | | | | | | obsolete 'getPrivateGraphicsConfiguration()'
| * JOGL Assets: Replace test-ntsc01-160x90.png w/ test-ntsc01-57x32.png (Save ↵Sven Gothel2013-12-281-1/+1
| | | | | | | | ~2 kB)
| * Bug 930 - OSX: Using 'Apple Software Renderer' GLRendererQuirks Quirk ↵Sven Gothel2013-12-231-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | GL4NeedsGL3Request not set GL3 core version validation failed due to missing braces around 'isES' _and_ term, where the latter consist out of 2 _or_ terms testing version mismatch. On OSX we validate a GL3 core context first and expect it to return a GL4 version if available, which in turn triggers the quirk GL4NeedsGL3Request. This behavior was disabled due to above mentioned bug, where the unqual major version caused the validation to fail. TestGLProfile01NEWT: Fixed 'GL4ES3' test, where 'GL4ES3' is only available if extension <code>GL_ARB_ES3_compatibility</code> is available as well.
| * Bug 929 - Reflect ES3 Compatibility with ES2Sven Gothel2013-12-213-24/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Map ES2 -> ES3 GLProfile, if available - EGLDrawableFactory: Don't query ES2 if ES3 is available - Fix queries and get methods (GL, GLContext and GLProfile): - glES3.isGLES2()==true and glES3.getGLES2()!=null - ctxES3.isGLES2()==true, - glES3Profile.isGLES2()==true - Enhance Unit test: TestGLProfile01NEWT - Test all GLProfile availability combinations based on implementing GLProfile - Test all GLProfile's isGL*() based on highest GLProfile identity - Test all GL's isGL*() based on highest GL identity.
| * Bug 925 - Refine GLContextImpl.setGLFunctionAvailability(..)'s ES version ↵Sven Gothel2013-12-211-4/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | validation Refine GLContextImpl.setGLFunctionAvailability(..)'s ES version validation: + // - fail if ES major-version mismatch: + // - request 1, >= 3 must be equal + // - request 2 must be [2..3] i.e. the following is accepted, otherwise fails: request has 1 1 2 2,3 3 3 4 4 ...
| * Bug 925 - Accept an ES3 Context, if reported via GL-Version-String w/o ↵Sven Gothel2013-12-215-32/+95
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | EGL_OPENGL_ES3_BIT_KHR Add Quirk 'GLES3ViaEGLES2Config': ES3 Context is used via EGL_OPENGL_ES2_BIT and 'version 2' for create context attributes. - GLContextImpl.setGLFunctionAvailability(..)'s ES version validation only fails if requested major version == 1 and doesn't match. Hence requesting major==2 and having version 3 is tolerated. - GLContextImpl.setGLFunctionAvailability(..)'s Quirks: requested-major < has-major -> Adding GLES3ViaEGLES2Config - EGLDrawableFactory.mapAvailableEGLESConfig(..): Reflects has-major version, i.e. GLES3ViaEGLES2Config situation where an ES2 request leads to an ES3 version. Note: All workarounds can be found via lookup of GLES3ViaEGLES2Config (as usual when using quirks).