From a4e9947d42dedaec8979119a0b5a6504c08984e3 Mon Sep 17 00:00:00 2001 From: rafalense Date: Thu, 25 Feb 2016 10:36:39 +0100 Subject: [PATCH] =?UTF-8?q?-=20Added=20swipe=20left/right=20to=20change=20?= =?UTF-8?q?between=20tabs=20-=20Added=20option=20to=20enable/disable=20inf?= =?UTF-8?q?inite=20swipe=20between=20tabs=20-=20Added=20new=20menu=20Plus?= =?UTF-8?q?=20and=20moved=20there=20all=20additional=20Plus=20features=20-?= =?UTF-8?q?=20Added=20option=20to=20show/hide=20direct=20share=20button=20?= =?UTF-8?q?in=20any=20chat=20-=20Added=20switch=20to=20use=20direct=20shar?= =?UTF-8?q?e=20without=20quoting=20sender=20-=20Added=20date=20indicator?= =?UTF-8?q?=20toast=20in=20chat=20-=20Added=20current=20download/upload=20?= =?UTF-8?q?size=20in=20chat=20screen=20-=20Added=20sort=20options=20(defau?= =?UTF-8?q?lt/unread)=20to=20all=20tabs=20-=20Added=20different=20options?= =?UTF-8?q?=20in=20groups/supergroups=20for=20admins=20when=20user=20avata?= =?UTF-8?q?r=20is=20clicked=20in=20chat=20screen:=20=E2=80=98Show=20profil?= =?UTF-8?q?e=E2=80=99,=20=E2=80=98Delete=20from=20group=E2=80=99=20and=20?= =?UTF-8?q?=E2=80=98Set=20as=20admin=E2=80=99=20-=20Added=20option=20to=20?= =?UTF-8?q?remove=20from=20admin=20list=20if=20user=20is=20already=20an=20?= =?UTF-8?q?admin=20-=20Added=20=E2=80=98Mark=20as=20read=E2=80=99=20for=20?= =?UTF-8?q?individual=20chats=20and=20=E2=80=98Mark=20all=20as=20read?= =?UTF-8?q?=E2=80=99=20for=20every=20tab=20-=20Added=20option=20in=20Plus?= =?UTF-8?q?=20settings=20to=20show=20username=20instead=20of=20mobile=20nu?= =?UTF-8?q?mber=20in=20menu=20-=20Bug=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- TMessagesProj/build.gradle | 18 +- .../config/debug/AndroidManifest.xml | 23 +- .../config/release/AndroidManifest.xml | 23 +- TMessagesProj/jni/Android.mk | 144 +- TMessagesProj/jni/gif.c | 847 --- TMessagesProj/jni/gif.h | 7 - TMessagesProj/jni/giflib/config.h | 13 - TMessagesProj/jni/giflib/dgif_lib.c | 1167 --- TMessagesProj/jni/giflib/gif_hash.c | 132 - TMessagesProj/jni/giflib/gif_hash.h | 39 - TMessagesProj/jni/giflib/gif_lib.h | 307 - TMessagesProj/jni/giflib/gif_lib_private.h | 59 - TMessagesProj/jni/giflib/gifalloc.c | 400 - TMessagesProj/jni/image.c | 31 +- TMessagesProj/jni/jni.c | 10 +- TMessagesProj/jni/libyuv/include/libyuv.h | 1 - .../jni/libyuv/include/libyuv/compare.h | 5 + .../jni/libyuv/include/libyuv/convert.h | 13 +- .../jni/libyuv/include/libyuv/convert_argb.h | 124 +- .../jni/libyuv/include/libyuv/convert_from.h | 14 +- .../libyuv/include/libyuv/convert_from_argb.h | 24 + .../jni/libyuv/include/libyuv/cpu_id.h | 9 +- .../libyuv/include/libyuv/format_conversion.h | 168 - .../libyuv/include/libyuv/planar_functions.h | 106 +- TMessagesProj/jni/libyuv/include/libyuv/row.h | 1643 +++-- .../jni/libyuv/include/libyuv/scale.h | 1 + .../jni/libyuv/include/libyuv/scale_argb.h | 1 - .../jni/libyuv/include/libyuv/scale_row.h | 282 +- .../jni/libyuv/include/libyuv/version.h | 2 +- .../jni/libyuv/include/libyuv/video_common.h | 8 +- TMessagesProj/jni/libyuv/source/compare.cc | 89 +- .../jni/libyuv/source/compare_common.cc | 2 + .../jni/libyuv/source/compare_neon.cc | 47 +- .../jni/libyuv/source/compare_posix.cc | 158 - .../jni/libyuv/source/compare_win.cc | 108 +- TMessagesProj/jni/libyuv/source/convert.cc | 602 +- .../jni/libyuv/source/convert_argb.cc | 831 ++- .../jni/libyuv/source/convert_from.cc | 605 +- .../jni/libyuv/source/convert_from_argb.cc | 540 +- .../jni/libyuv/source/convert_to_argb.cc | 59 +- .../jni/libyuv/source/convert_to_i420.cc | 52 +- TMessagesProj/jni/libyuv/source/cpu_id.cc | 200 +- .../jni/libyuv/source/format_conversion.cc | 554 -- .../jni/libyuv/source/mjpeg_decoder.cc | 12 +- .../jni/libyuv/source/mjpeg_validate.cc | 58 +- .../jni/libyuv/source/planar_functions.cc | 1255 ++-- TMessagesProj/jni/libyuv/source/rotate.cc | 962 +-- .../jni/libyuv/source/rotate_argb.cc | 92 +- .../jni/libyuv/source/rotate_mips.cc | 9 +- .../jni/libyuv/source/rotate_neon.cc | 8 +- .../jni/libyuv/source/rotate_neon64.cc | 595 +- TMessagesProj/jni/libyuv/source/row_any.cc | 1245 ++-- TMessagesProj/jni/libyuv/source/row_common.cc | 1120 ++- TMessagesProj/jni/libyuv/source/row_mips.cc | 226 +- TMessagesProj/jni/libyuv/source/row_neon.cc | 1000 +-- TMessagesProj/jni/libyuv/source/row_neon64.cc | 2580 +++---- TMessagesProj/jni/libyuv/source/row_posix.cc | 6443 ----------------- TMessagesProj/jni/libyuv/source/row_win.cc | 5496 ++++++-------- TMessagesProj/jni/libyuv/source/row_x86.asm | 146 - TMessagesProj/jni/libyuv/source/scale.cc | 605 +- TMessagesProj/jni/libyuv/source/scale_argb.cc | 267 +- .../jni/libyuv/source/scale_common.cc | 100 +- TMessagesProj/jni/libyuv/source/scale_mips.cc | 10 - TMessagesProj/jni/libyuv/source/scale_neon.cc | 285 +- .../jni/libyuv/source/scale_neon64.cc | 537 +- .../jni/libyuv/source/scale_posix.cc | 1315 ---- TMessagesProj/jni/libyuv/source/scale_win.cc | 891 +-- .../jni/libyuv/source/video_common.cc | 2 +- TMessagesProj/jni/libyuv/source/x86inc.asm | 1136 --- TMessagesProj/jni/sqlite/sqlite3.c | 1 + TMessagesProj/jni/utils.h | 2 +- TMessagesProj/src/main/AndroidManifest.xml | 39 +- .../org/telegram/SQLite/SQLiteCursor.java | 2 +- .../org/telegram/SQLite/SQLiteDatabase.java | 2 +- .../org/telegram/SQLite/SQLiteException.java | 2 +- .../telegram/SQLite/SQLiteNoRowException.java | 2 +- .../SQLite/SQLitePreparedStatement.java | 6 +- .../telegram/messenger/ApplicationLoader.java | 179 +- .../org/telegram/messenger/DispatchQueue.java | 2 +- .../telegram/messenger/FileLoadOperation.java | 92 +- .../org/telegram/messenger/FileLoader.java | 89 +- .../java/org/telegram/messenger/FileLog.java | 20 +- .../messenger/FileUploadOperation.java | 2 +- .../telegram/messenger/MessageKeyData.java | 2 +- .../org/telegram/messenger/UserConfig.java | 8 +- .../org/telegram/messenger/Utilities.java | 22 +- .../org/telegram/ui/ActionBar/ActionBar.java | 2 +- .../ui/ActionBar/ActionBarLayout.java | 2 +- .../telegram/ui/ActionBar/ActionBarMenu.java | 2 +- .../ui/ActionBar/ActionBarMenuItem.java | 4 +- .../ui/ActionBar/ActionBarPopupWindow.java | 2 +- .../telegram/ui/ActionBar/BaseFragment.java | 2 +- .../ui/ActionBar/DrawerLayoutContainer.java | 56 +- .../telegram/ui/ActionBar/MenuDrawable.java | 2 +- .../ui/Adapters/BaseFragmentAdapter.java | 2 +- .../ui/Adapters/BaseLocationAdapter.java | 2 +- .../ui/Adapters/BaseSearchAdapter.java | 2 +- .../ui/Adapters/BaseSectionsAdapter.java | 2 +- .../ui/Adapters/ChatActivityAdapter.java | 2 +- .../telegram/ui/Adapters/ContactsAdapter.java | 34 +- .../telegram/ui/Adapters/CountryAdapter.java | 2 +- .../ui/Adapters/CountrySearchAdapter.java | 2 +- .../telegram/ui/Adapters/DialogsAdapter.java | 199 +- .../ui/Adapters/DialogsSearchAdapter.java | 2 +- .../ui/Adapters/DrawerLayoutAdapter.java | 14 +- .../ui/Adapters/LocationActivityAdapter.java | 2 +- .../LocationActivitySearchAdapter.java | 2 +- .../telegram/ui/Adapters/MentionsAdapter.java | 529 +- .../telegram/ui/Adapters/SearchAdapter.java | 2 +- .../telegram/ui/Adapters/StickersAdapter.java | 2 +- .../org/telegram/ui/BlockedUsersActivity.java | 2 +- .../java/org/telegram/ui/Cells/BaseCell.java | 2 +- .../org/telegram/ui/Cells/ChatActionCell.java | 12 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 60 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 287 +- .../telegram/ui/Cells/ChatContactCell.java | 2 +- .../org/telegram/ui/Cells/ChatMediaCell.java | 342 +- .../telegram/ui/Cells/ChatMessageCell.java | 138 +- .../org/telegram/ui/Cells/DialogCell.java | 91 +- .../org/telegram/ui/Cells/DividerCell.java | 2 +- .../telegram/ui/Cells/DrawerActionCell.java | 2 +- .../telegram/ui/Cells/DrawerProfileCell.java | 26 +- .../java/org/telegram/ui/Cells/EmptyCell.java | 2 +- .../telegram/ui/Cells/GreySectionCell.java | 2 +- .../telegram/ui/Cells/HashtagSearchCell.java | 2 +- .../org/telegram/ui/Cells/HeaderCell.java | 2 +- .../telegram/ui/Cells/LetterSectionCell.java | 2 +- .../org/telegram/ui/Cells/LoadingCell.java | 2 +- .../org/telegram/ui/Cells/LocationCell.java | 2 +- .../ui/Cells/LocationLoadingCell.java | 2 +- .../ui/Cells/LocationPoweredCell.java | 2 +- .../org/telegram/ui/Cells/MentionCell.java | 4 +- .../telegram/ui/Cells/PhotoEditToolCell.java | 2 +- .../ui/Cells/PhotoPickerAlbumsCell.java | 2 +- .../ui/Cells/PhotoPickerPhotoCell.java | 2 +- .../ui/Cells/PhotoPickerSearchCell.java | 9 +- .../telegram/ui/Cells/ProfileSearchCell.java | 24 +- .../telegram/ui/Cells/SendLocationCell.java | 2 +- .../org/telegram/ui/Cells/SessionCell.java | 2 +- .../ui/Cells/ShadowBottomSectionCell.java | 2 +- .../telegram/ui/Cells/ShadowSectionCell.java | 2 +- .../telegram/ui/Cells/SharedDocumentCell.java | 2 +- .../ui/Cells/SharedMediaSectionCell.java | 2 +- .../ui/Cells/SharedPhotoVideoCell.java | 2 +- .../org/telegram/ui/Cells/StickerCell.java | 2 +- .../telegram/ui/Cells/StickerEmojiCell.java | 2 +- .../org/telegram/ui/Cells/TextBlockCell.java | 2 +- .../java/org/telegram/ui/Cells/TextCell.java | 11 +- .../org/telegram/ui/Cells/TextCheckCell.java | 2 +- .../org/telegram/ui/Cells/TextColorCell.java | 2 +- .../org/telegram/ui/Cells/TextDetailCell.java | 2 +- .../ui/Cells/TextDetailSettingsCell.java | 2 +- .../org/telegram/ui/Cells/TextInfoCell.java | 2 +- .../ui/Cells/TextInfoPrivacyCell.java | 4 +- .../telegram/ui/Cells/TextSettingsCell.java | 2 +- .../java/org/telegram/ui/Cells/UserCell.java | 2 +- .../telegram/ui/ChangeChatNameActivity.java | 2 +- .../org/telegram/ui/ChangeNameActivity.java | 10 +- .../org/telegram/ui/ChangePhoneActivity.java | 6 +- .../telegram/ui/ChangePhoneHelpActivity.java | 2 +- .../telegram/ui/ChangeUsernameActivity.java | 2 +- .../java/org/telegram/ui/ChatActivity.java | 1045 ++- .../ui/Components/AvatarDrawable.java | 2 +- .../telegram/ui/Components/AvatarUpdater.java | 4 +- .../ui/Components/BackupImageView.java | 2 +- .../ui/Components/ChatActivityEnterView.java | 289 +- .../org/telegram/ui/Components/CheckBox.java | 2 +- .../ui/Components/ClippingImageView.java | 2 +- .../org/telegram/ui/Components/EmojiView.java | 510 +- .../ui/Components/ForegroundDetector.java | 2 +- .../ui/Components/FrameLayoutFixed.java | 2 +- .../telegram/ui/Components/GifDrawable.java | 409 -- .../ui/Components/IdenticonDrawable.java | 2 +- .../telegram/ui/Components/LayoutHelper.java | 2 +- .../ui/Components/LetterSectionsListView.java | 2 +- .../ui/Components/LineProgressView.java | 2 +- .../ui/Components/MapPlaceholderDrawable.java | 2 +- .../ui/Components/PagerSlidingTabStrip.java | 12 +- .../telegram/ui/Components/PhotoCropView.java | 2 +- .../ui/Components/PhotoEditorSeekBar.java | 2 +- .../ui/Components/PhotoFilterBlurControl.java | 2 +- .../ui/Components/PhotoFilterView.java | 2 +- .../PhotoViewerCaptionEnterView.java | 24 +- .../org/telegram/ui/Components/Point.java | 2 +- .../ui/Components/PopupAudioView.java | 2 +- .../telegram/ui/Components/ProgressView.java | 2 +- .../ui/Components/RadialProgress.java | 110 +- .../ui/Components/RecordStatusDrawable.java | 2 +- .../java/org/telegram/ui/Components/Rect.java | 2 +- .../ui/Components/RecyclerListView.java | 80 +- .../ui/Components/ResourceLoader.java | 62 +- .../ui/Components/SectionsListView.java | 2 +- .../org/telegram/ui/Components/SeekBar.java | 2 +- .../ui/Components/SendingFileDrawable.java | 2 +- .../ui/Components/SendingFileEx2Drawable.java | 2 +- .../ui/Components/SendingFileExDrawable.java | 2 +- .../ui/Components/SimpleTextView.java | 2 +- .../java/org/telegram/ui/Components/Size.java | 2 +- .../org/telegram/ui/Components/SlideView.java | 2 +- .../ui/Components/SlidingTabView.java | 2 +- .../ui/Components/StaticLayoutEx.java | 2 +- .../org/telegram/ui/Components/Switch.java | 34 +- .../telegram/ui/Components/TimerDrawable.java | 2 +- .../telegram/ui/Components/TypefaceSpan.java | 32 +- .../ui/Components/TypingDotsDrawable.java | 2 +- .../ui/Components/URLSpanNoUnderline.java | 2 +- .../ui/Components/VideoSeekBarView.java | 2 +- .../ui/Components/VideoTimelineView.java | 2 +- .../org/telegram/ui/ContactAddActivity.java | 2 +- .../org/telegram/ui/ContactsActivity.java | 2 +- .../telegram/ui/CountrySelectActivity.java | 2 +- .../telegram/ui/DocumentSelectActivity.java | 2 +- .../org/telegram/ui/GroupCreateActivity.java | 2 +- .../telegram/ui/GroupCreateFinalActivity.java | 2 +- .../org/telegram/ui/GroupInviteActivity.java | 2 +- .../org/telegram/ui/IdenticonActivity.java | 2 +- .../java/org/telegram/ui/IntroActivity.java | 2 +- .../telegram/ui/LanguageSelectActivity.java | 4 +- .../org/telegram/ui/LastSeenActivity.java | 13 +- .../telegram/ui/LastSeenUsersActivity.java | 2 +- .../java/org/telegram/ui/LaunchActivity.java | 78 +- .../org/telegram/ui/LocationActivity.java | 22 +- .../java/org/telegram/ui/LoginActivity.java | 48 +- .../java/org/telegram/ui/MediaActivity.java | 8 +- .../ui/NotificationsSettingsActivity.java | 2 +- .../org/telegram/ui/PasscodeActivity.java | 2 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 12 +- .../org/telegram/ui/PhotoCropActivity.java | 2 +- .../org/telegram/ui/PhotoPickerActivity.java | 136 +- .../java/org/telegram/ui/PhotoViewer.java | 145 +- .../ui/PopupNotificationActivity.java | 7 +- .../telegram/ui/PrivacySettingsActivity.java | 35 +- .../java/org/telegram/ui/ProfileActivity.java | 175 +- .../ui/ProfileNotificationsActivity.java | 2 +- .../org/telegram/ui/SecretPhotoViewer.java | 2 +- .../org/telegram/ui/SessionsActivity.java | 2 +- .../org/telegram/ui/SettingsActivity.java | 467 +- .../java/org/telegram/ui/ThemingActivity.java | 2 +- .../org/telegram/ui/ThemingChatActivity.java | 10 +- .../org/telegram/ui/ThemingChatsActivity.java | 6 +- .../telegram/ui/ThemingContactsActivity.java | 4 +- .../telegram/ui/ThemingDrawerActivity.java | 4 +- .../telegram/ui/ThemingProfileActivity.java | 4 +- .../ui/TwoStepVerificationActivity.java | 2 +- .../org/telegram/ui/VideoEditorActivity.java | 56 +- .../org/telegram/ui/WallpapersActivity.java | 8 +- .../src/main/res/drawable-xxhdpi/Thumbs.db | Bin 64512 -> 1097728 bytes .../main/res/drawable/bar_selector_lock.xml | 2 +- .../main/res/drawable/bar_selector_picker.xml | 2 +- .../main/res/drawable/bar_selector_white.xml | 2 +- .../res/drawable/floating_user_states.xml | 2 +- .../src/main/res/values-ar/strings.xml | 40 +- .../src/main/res/values-ca/strings.xml | 163 +- .../src/main/res/values-de/strings.xml | 137 +- .../src/main/res/values-es/strings.xml | 100 +- .../src/main/res/values-fr/strings.xml | 79 +- .../src/main/res/values-gl/strings.xml | 69 +- .../src/main/res/values-hi/strings.xml | 71 +- .../src/main/res/values-hr/strings.xml | 3 +- .../src/main/res/values-it/strings.xml | 90 +- .../src/main/res/values-ko/strings.xml | 42 +- .../src/main/res/values-ms/strings.xml | 6 - .../src/main/res/values-nl/strings.xml | 130 +- .../src/main/res/values-pl/strings.xml | 113 +- .../src/main/res/values-pt-rBR/strings.xml | 127 +- .../src/main/res/values-pt-rPT/strings.xml | 39 +- .../src/main/res/values-ru/strings.xml | 187 +- .../src/main/res/values-tr/strings.xml | 56 +- .../src/main/res/values-v21/styles.xml | 2 +- .../src/main/res/values-zh-rCN/strings.xml | 296 +- .../src/main/res/values-zh-rTW/strings.xml | 355 +- TMessagesProj/src/main/res/values/strings.xml | 82 +- 273 files changed, 17155 insertions(+), 27306 deletions(-) delete mode 100644 TMessagesProj/jni/gif.c delete mode 100644 TMessagesProj/jni/gif.h delete mode 100644 TMessagesProj/jni/giflib/config.h delete mode 100644 TMessagesProj/jni/giflib/dgif_lib.c delete mode 100644 TMessagesProj/jni/giflib/gif_hash.c delete mode 100644 TMessagesProj/jni/giflib/gif_hash.h delete mode 100644 TMessagesProj/jni/giflib/gif_lib.h delete mode 100644 TMessagesProj/jni/giflib/gif_lib_private.h delete mode 100644 TMessagesProj/jni/giflib/gifalloc.c delete mode 100644 TMessagesProj/jni/libyuv/include/libyuv/format_conversion.h delete mode 100644 TMessagesProj/jni/libyuv/source/compare_posix.cc delete mode 100644 TMessagesProj/jni/libyuv/source/format_conversion.cc delete mode 100644 TMessagesProj/jni/libyuv/source/row_posix.cc delete mode 100644 TMessagesProj/jni/libyuv/source/row_x86.asm delete mode 100644 TMessagesProj/jni/libyuv/source/scale_posix.cc delete mode 100644 TMessagesProj/jni/libyuv/source/x86inc.asm delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java diff --git a/README.md b/README.md index 9ef8e180..29052253 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -### Plus Messenger for Android +### Plus Messenger for Android (http://plusmessenger.org) This is an UNOFFICIAL app that uses [Telegram's API](https://core.telegram.org/api) diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 6bdcda4f..4058cf00 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -6,7 +6,8 @@ repositories { dependencies { compile 'com.android.support:support-v4:23.1.+' - compile 'com.google.android.gms:play-services:3.2.+' + compile "com.google.android.gms:play-services-gcm:8.4.0" + compile "com.google.android.gms:play-services-maps:8.4.0" compile 'net.hockeyapp.android:HockeySDK:3.6.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+' } @@ -16,6 +17,8 @@ android { buildToolsVersion '23.0.2' useLibrary 'org.apache.http.legacy' + //defaultConfig.applicationId = "org.telegram.messenger" + defaultConfig.applicationId = "org.telegram.plus" compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 @@ -25,6 +28,10 @@ android { signingConfigs { debug { storeFile file("config/debug.keystore") + //storeFile file("config/release.keystore") + //storePassword RELEASE_STORE_PASSWORD + //keyAlias RELEASE_KEY_ALIAS + //keyPassword RELEASE_KEY_PASSWORD } release { @@ -47,6 +54,8 @@ android { debuggable false jniDebuggable false //signingConfig signingConfigs.release + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } foss { @@ -79,10 +88,9 @@ android { } defaultConfig { - applicationId "org.telegram.plus" - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 23 - versionCode 689 - versionName "3.3.1.1" + versionCode 736 + versionName "3.4.2.5" } } diff --git a/TMessagesProj/config/debug/AndroidManifest.xml b/TMessagesProj/config/debug/AndroidManifest.xml index 1891773a..c524d434 100644 --- a/TMessagesProj/config/debug/AndroidManifest.xml +++ b/TMessagesProj/config/debug/AndroidManifest.xml @@ -27,7 +27,7 @@ android:label="Plus beta" tools:replace="label" android:theme="@style/Theme.TMessages.Start" - android:name=".ApplicationLoader" + android:name="org.telegram.messenger.ApplicationLoader" android:hardwareAccelerated="@bool/useHardwareAcceleration" android:largeHeap="true"> @@ -36,7 +36,8 @@ @@ -44,6 +45,24 @@ + + + + + + + + + + + + diff --git a/TMessagesProj/config/release/AndroidManifest.xml b/TMessagesProj/config/release/AndroidManifest.xml index 4d673eb9..c0a8cdb4 100644 --- a/TMessagesProj/config/release/AndroidManifest.xml +++ b/TMessagesProj/config/release/AndroidManifest.xml @@ -25,7 +25,7 @@ android:icon="@drawable/ic_launcher" android:label="@string/ShortAppName" android:theme="@style/Theme.TMessages.Start" - android:name=".ApplicationLoader" + android:name="org.telegram.messenger.ApplicationLoader" android:hardwareAccelerated="@bool/useHardwareAcceleration" android:largeHeap="true"> @@ -34,7 +34,8 @@ @@ -42,6 +43,24 @@ + + + + + + + + + + + + diff --git a/TMessagesProj/jni/Android.mk b/TMessagesProj/jni/Android.mk index 6bcfa754..451dc20e 100644 --- a/TMessagesProj/jni/Android.mk +++ b/TMessagesProj/jni/Android.mk @@ -1,5 +1,57 @@ LOCAL_PATH := $(call my-dir) +LOCAL_MODULE := avutil + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavutil.a +else + ifeq ($(TARGET_ARCH_ABI),armeabi) + LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavutil.a + else + ifeq ($(TARGET_ARCH_ABI),x86) + LOCAL_SRC_FILES := ./ffmpeg/i686/libavutil.a + endif + endif +endif + +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := avformat + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavformat.a +else + ifeq ($(TARGET_ARCH_ABI),armeabi) + LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavformat.a + else + ifeq ($(TARGET_ARCH_ABI),x86) + LOCAL_SRC_FILES := ./ffmpeg/i686/libavformat.a + endif + endif +endif + +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := avcodec + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavcodec.a +else + ifeq ($(TARGET_ARCH_ABI),armeabi) + LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavcodec.a + else + ifeq ($(TARGET_ARCH_ABI),x86) + LOCAL_SRC_FILES := ./ffmpeg/i686/libavcodec.a + endif + endif +endif + +include $(PREBUILT_STATIC_LIBRARY) + include $(CLEAR_VARS) LOCAL_MODULE := crypto @@ -26,8 +78,8 @@ LOCAL_MODULE := breakpad LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing LOCAL_C_INCLUDES := \ -./breakpad/common/android/include \ -./breakpad +$(LOCAL_PATH)/breakpad/common/android/include \ +$(LOCAL_PATH)/breakpad LOCAL_SRC_FILES := \ ./breakpad/client/linux/crash_generation/crash_generation_client.cc \ @@ -57,7 +109,7 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -frtti -DHAVE_PTHREAD -finline-functions -ffast-math -Os -LOCAL_C_INCLUDES += ./boringssl/include/ +LOCAL_C_INCLUDES += $(LOCAL_PATH)/boringssl/include/ LOCAL_ARM_MODE := arm LOCAL_MODULE := tgnet LOCAL_STATIC_LIBRARIES := crypto @@ -85,15 +137,12 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD -finline-functions -ffast-math -ffunction-sections -fdata-sections -Os -LOCAL_C_INCLUDES += ./libwebp/src +LOCAL_C_INCLUDES += $(LOCAL_PATH)/libwebp/src LOCAL_ARM_MODE := arm LOCAL_STATIC_LIBRARIES := cpufeatures LOCAL_MODULE := webp ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),) - # Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal - # instructions to be generated for armv7a code. Instead target the neon code - # specifically. NEON := c.neon else NEON := c @@ -185,19 +234,14 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false -LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad -LOCAL_MODULE := tmessages.15 +LOCAL_MODULE := tmessages.17 LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno -LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math +LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++11 LOCAL_LDLIBS := -ljnigraphics -llog -lz -ifeq ($(TARGET_ARCH_ABI),armeabi) - LOCAL_ARM_MODE := thumb -else - LOCAL_ARM_MODE := arm -endif +LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad avformat avcodec avutil LOCAL_SRC_FILES := \ ./opus/src/opus.c \ @@ -211,6 +255,23 @@ LOCAL_SRC_FILES := \ ./opus/src/mlp.c \ ./opus/src/mlp_data.c +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_ARM_MODE := arm + LOCAL_CPPFLAGS += -DLIBYUV_NEON + LOCAL_CFLAGS += -DLIBYUV_NEON +else + ifeq ($(TARGET_ARCH_ABI),armeabi) + LOCAL_ARM_MODE := arm + + else + ifeq ($(TARGET_ARCH_ABI),x86) + LOCAL_ARM_MODE := arm + LOCAL_SRC_FILE += \ + ./libyuv/source/row_x86.asm + endif + endif +endif + LOCAL_SRC_FILES += \ ./opus/silk/CNG.c \ ./opus/silk/code_signs.c \ @@ -346,21 +407,18 @@ LOCAL_SRC_FILES += \ ./opus/opusfile/opusfile.c \ ./opus/opusfile/stream.c -LOCAL_SRC_FILES += \ -./giflib/dgif_lib.c \ -./giflib/gifalloc.c - LOCAL_C_INCLUDES := \ -./opus/include \ -./opus/silk \ -./opus/silk/fixed \ -./opus/celt \ -./opus/ \ -./opus/opusfile \ -./libyuv/include \ -./boringssl/include \ -./breakpad/common/android/include \ -./breakpad +$(LOCAL_PATH)/opus/include \ +$(LOCAL_PATH)/opus/silk \ +$(LOCAL_PATH)/opus/silk/fixed \ +$(LOCAL_PATH)/opus/celt \ +$(LOCAL_PATH)/opus/ \ +$(LOCAL_PATH)/opus/opusfile \ +$(LOCAL_PATH)/libyuv/include \ +$(LOCAL_PATH)/boringssl/include \ +$(LOCAL_PATH)/breakpad/common/android/include \ +$(LOCAL_PATH)/breakpad \ +$(LOCAL_PATH)/ffmpeg/include LOCAL_SRC_FILES += \ ./libjpeg/jcapimin.c \ @@ -413,8 +471,8 @@ LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \ ./libyuv/source/compare_common.cc \ -./libyuv/source/compare_neon.cc \ -./libyuv/source/compare_posix.cc \ +./libyuv/source/compare_gcc.cc \ +./libyuv/source/compare_neon64.cc \ ./libyuv/source/compare_win.cc \ ./libyuv/source/compare.cc \ ./libyuv/source/convert_argb.cc \ @@ -425,32 +483,42 @@ LOCAL_SRC_FILES += \ ./libyuv/source/convert_to_i420.cc \ ./libyuv/source/convert.cc \ ./libyuv/source/cpu_id.cc \ -./libyuv/source/format_conversion.cc \ ./libyuv/source/mjpeg_decoder.cc \ ./libyuv/source/mjpeg_validate.cc \ ./libyuv/source/planar_functions.cc \ +./libyuv/source/rotate_any.cc \ ./libyuv/source/rotate_argb.cc \ +./libyuv/source/rotate_common.cc \ +./libyuv/source/rotate_gcc.cc \ ./libyuv/source/rotate_mips.cc \ -./libyuv/source/rotate_neon.cc \ ./libyuv/source/rotate_neon64.cc \ +./libyuv/source/rotate_win.cc \ ./libyuv/source/rotate.cc \ ./libyuv/source/row_any.cc \ ./libyuv/source/row_common.cc \ +./libyuv/source/row_gcc.cc \ ./libyuv/source/row_mips.cc \ -./libyuv/source/row_neon.cc \ ./libyuv/source/row_neon64.cc \ -./libyuv/source/row_posix.cc \ ./libyuv/source/row_win.cc \ +./libyuv/source/scale_any.cc \ ./libyuv/source/scale_argb.cc \ ./libyuv/source/scale_common.cc \ +./libyuv/source/scale_gcc.cc \ ./libyuv/source/scale_mips.cc \ -./libyuv/source/scale_neon.cc \ ./libyuv/source/scale_neon64.cc \ -./libyuv/source/scale_posix.cc \ ./libyuv/source/scale_win.cc \ ./libyuv/source/scale.cc \ ./libyuv/source/video_common.cc +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_CFLAGS += -DLIBYUV_NEON + LOCAL_SRC_FILES += \ + ./libyuv/source/compare_neon.cc.neon \ + ./libyuv/source/rotate_neon.cc.neon \ + ./libyuv/source/row_neon.cc.neon \ + ./libyuv/source/scale_neon.cc.neon +endif + LOCAL_SRC_FILES += \ ./jni.c \ ./sqlite_cursor.c \ @@ -458,10 +526,10 @@ LOCAL_SRC_FILES += \ ./sqlite_statement.c \ ./sqlite.c \ ./audio.c \ -./gif.c \ ./utils.c \ ./image.c \ ./video.c \ +./gifvideo.cpp \ ./TgNetWrapper.cpp \ ./NativeLoader.cpp diff --git a/TMessagesProj/jni/gif.c b/TMessagesProj/jni/gif.c deleted file mode 100644 index 64dda479..00000000 --- a/TMessagesProj/jni/gif.c +++ /dev/null @@ -1,847 +0,0 @@ -//thanks to https://github.com/koral--/android-gif-drawable -/* - MIT License - Copyright (c) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - // Copyright (c) 2011 Google Inc. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions are - // met: - // - // * Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // * Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following disclaimer - // in the documentation and/or other materials provided with the - // distribution. - // * Neither the name of Google Inc. nor the names of its - // contributors may be used to endorse or promote products derived from - // this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond - */ - -#include -#include -#include -#include -#include "gif.h" -#include "giflib/gif_lib.h" - -#define D_GIF_ERR_NO_FRAMES 1000 -#define D_GIF_ERR_INVALID_SCR_DIMS 1001 -#define D_GIF_ERR_INVALID_IMG_DIMS 1002 -#define D_GIF_ERR_IMG_NOT_CONFINED 1003 - -typedef struct { - uint8_t blue; - uint8_t green; - uint8_t red; - uint8_t alpha; -} argb; - -typedef struct { - unsigned int duration; - int transpIndex; - unsigned char disposalMethod; -} FrameInfo; - -typedef struct { - GifFileType *gifFilePtr; - unsigned long lastFrameReaminder; - unsigned long nextStartTime; - int currentIndex; - unsigned int lastDrawIndex; - FrameInfo *infos; - argb *backupPtr; - int startPos; - unsigned char *rasterBits; - char *comment; - unsigned short loopCount; - int currentLoop; - jfloat speedFactor; -} GifInfo; - -static ColorMapObject *defaultCmap = NULL; - -static ColorMapObject *genDefColorMap(void) { - ColorMapObject *cmap = GifMakeMapObject(256, NULL); - if (cmap != NULL) { - int iColor; - for (iColor = 0; iColor < 256; iColor++) { - cmap->Colors[iColor].Red = (GifByteType) iColor; - cmap->Colors[iColor].Green = (GifByteType) iColor; - cmap->Colors[iColor].Blue = (GifByteType) iColor; - } - } - return cmap; -} - -jint gifOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { - defaultCmap = genDefColorMap(); - if (defaultCmap == NULL) { - return -1; - } - return JNI_VERSION_1_6; -} - -void gifOnJNIUnload(JavaVM *vm, void *reserved) { - GifFreeMapObject(defaultCmap); -} - -static int fileReadFunc(GifFileType *gif, GifByteType *bytes, int size) { - FILE *file = (FILE *)gif->UserData; - return fread(bytes, 1, size, file); -} - -static int fileRewindFun(GifInfo *info) { - return fseek(info->gifFilePtr->UserData, info->startPos, SEEK_SET); -} - -static unsigned long getRealTime() { - struct timespec ts; - const clockid_t id = CLOCK_MONOTONIC; - if (id != (clockid_t) - 1 && clock_gettime(id, &ts) != -1) { - return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; - } - return -1; -} - -static void cleanUp(GifInfo *info) { - if (info->backupPtr) { - free(info->backupPtr); - info->backupPtr = NULL; - } - if (info->infos) { - free(info->infos); - info->infos = NULL; - } - if (info->rasterBits) { - free(info->rasterBits); - info->rasterBits = NULL; - } - if (info->comment) { - free(info->comment); - info->comment = NULL; - } - - GifFileType *GifFile = info->gifFilePtr; - if (GifFile->SColorMap == defaultCmap) { - GifFile->SColorMap = NULL; - } - if (GifFile->SavedImages != NULL) { - SavedImage *sp; - for (sp = GifFile->SavedImages; sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { - if (sp->ImageDesc.ColorMap != NULL) { - GifFreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; - } - } - free(GifFile->SavedImages); - GifFile->SavedImages = NULL; - } - DGifCloseFile(GifFile); - free(info); -} - -static int getComment(GifByteType *Bytes, char **cmt) { - unsigned int len = (unsigned int) Bytes[0]; - unsigned int offset = *cmt != NULL ? strlen(*cmt) : 0; - char *ret = realloc(*cmt, (len + offset + 1) * sizeof(char)); - if (ret != NULL) { - memcpy(ret + offset, &Bytes[1], len); - ret[len + offset] = 0; - *cmt = ret; - return GIF_OK; - } - return GIF_ERROR; -} - -static void packARGB32(argb *pixel, GifByteType alpha, GifByteType red, GifByteType green, GifByteType blue) { - pixel->alpha = alpha; - pixel->red = red; - pixel->green = green; - pixel->blue = blue; -} - -static void getColorFromTable(int idx, argb *dst, const ColorMapObject *cmap) { - int colIdx = (idx >= cmap->ColorCount) ? 0 : idx; - GifColorType *col = &cmap->Colors[colIdx]; - packARGB32(dst, 0xFF, col->Red, col->Green, col->Blue); -} - -static void eraseColor(argb *bm, int w, int h, argb color) { - int i; - for (i = 0; i < w * h; i++) { - *(bm + i) = color; - } -} - -static inline bool setupBackupBmp(GifInfo *info, short transpIndex) { - GifFileType *fGIF = info->gifFilePtr; - info->backupPtr = calloc(fGIF->SWidth * fGIF->SHeight, sizeof(argb)); - if (!info->backupPtr) { - info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return false; - } - argb paintingColor; - if (transpIndex == -1) { - getColorFromTable(fGIF->SBackGroundColor, &paintingColor, fGIF->SColorMap); - } else { - packARGB32(&paintingColor, 0, 0, 0, 0); - } - eraseColor(info->backupPtr, fGIF->SWidth, fGIF->SHeight, paintingColor); - return true; -} - -static int readExtensions(int ExtFunction, GifByteType *ExtData, GifInfo *info) { - if (ExtData == NULL) { - return GIF_OK; - } - if (ExtFunction == GRAPHICS_EXT_FUNC_CODE && ExtData[0] == 4) { - FrameInfo *fi = &info->infos[info->gifFilePtr->ImageCount]; - fi->transpIndex = -1; - char *b = (char*) ExtData + 1; - short delay = ((b[2] << 8) | b[1]); - fi->duration = delay > 1 ? delay * 10 : 100; - fi->disposalMethod = ((b[0] >> 2) & 7); - if (ExtData[1] & 1) { - fi->transpIndex = 0xff & b[3]; - } - if (fi->disposalMethod == 3 && info->backupPtr == NULL) { - if (!setupBackupBmp(info, fi->transpIndex)) { - return GIF_ERROR; - } - } - } else if (ExtFunction == COMMENT_EXT_FUNC_CODE) { - if (getComment(ExtData, &info->comment) == GIF_ERROR) { - info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } else if (ExtFunction == APPLICATION_EXT_FUNC_CODE && ExtData[0] == 11) { - if (strncmp("NETSCAPE2.0", &ExtData[1], 11) == 0 || strncmp("ANIMEXTS1.0", &ExtData[1], 11) == 0) { - if (DGifGetExtensionNext(info->gifFilePtr, &ExtData, &ExtFunction) == GIF_ERROR) { - return GIF_ERROR; - } - if (ExtFunction == APPLICATION_EXT_FUNC_CODE && ExtData[0] == 3 && ExtData[1] == 1) { - info->loopCount = (unsigned short) (ExtData[2] + (ExtData[3] << 8)); - } - } - } - return GIF_OK; -} - -static int DDGifSlurp(GifFileType *GifFile, GifInfo* info, bool shouldDecode) { - GifRecordType RecordType; - GifByteType *ExtData; - int codeSize; - int ExtFunction; - size_t ImageSize; - do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { - return (GIF_ERROR); - } - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - - if (DGifGetImageDesc(GifFile, !shouldDecode) == GIF_ERROR) { - return (GIF_ERROR); - } - int i = shouldDecode ? info->currentIndex : GifFile->ImageCount - 1; - SavedImage *sp = &GifFile->SavedImages[i]; - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - if (sp->ImageDesc.Width < 1 || sp->ImageDesc.Height < 1 || ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { - GifFile->Error = D_GIF_ERR_INVALID_IMG_DIMS; - return GIF_ERROR; - } - if (sp->ImageDesc.Width > GifFile->SWidth || sp->ImageDesc.Height > GifFile->SHeight) { - GifFile->Error = D_GIF_ERR_IMG_NOT_CONFINED; - return GIF_ERROR; - } - if (shouldDecode) { - sp->RasterBits = info->rasterBits; - if (sp->ImageDesc.Interlace) { - int i, j; - int InterlacedOffset[] = { 0, 4, 2, 1 }; - int InterlacedJumps[] = { 8, 8, 4, 2 }; - for (i = 0; i < 4; i++) { - for (j = InterlacedOffset[i]; j < sp->ImageDesc.Height; j += InterlacedJumps[i]) { - if (DGifGetLine(GifFile, sp->RasterBits + j * sp->ImageDesc.Width, sp->ImageDesc.Width) == GIF_ERROR) { - return GIF_ERROR; - } - } - } - } else { - if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) == GIF_ERROR) { - return (GIF_ERROR); - } - } - if (info->currentIndex >= GifFile->ImageCount - 1) { - if (info->loopCount > 0) { - info->currentLoop++; - } - if (fileRewindFun(info) != 0) { - info->gifFilePtr->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - } - return GIF_OK; - } else { - if (DGifGetCode(GifFile, &codeSize, &ExtData) == GIF_ERROR) { - return (GIF_ERROR); - } - while (ExtData != NULL) { - if (DGifGetCodeNext(GifFile, &ExtData) == GIF_ERROR) { - return (GIF_ERROR); - } - } - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) == GIF_ERROR) { - return (GIF_ERROR); - } - - if (!shouldDecode) { - FrameInfo *tmpInfos = realloc(info->infos, (GifFile->ImageCount + 1) * sizeof(FrameInfo)); - if (tmpInfos == NULL) { - return GIF_ERROR; - } - info->infos = tmpInfos; - if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) { - return GIF_ERROR; - } - } - while (ExtData != NULL) { - if (DGifGetExtensionNext(GifFile, &ExtData, &ExtFunction) == GIF_ERROR) { - return (GIF_ERROR); - } - if (!shouldDecode) { - if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) { - return GIF_ERROR; - } - } - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: - break; - } - } while (RecordType != TERMINATE_RECORD_TYPE); - bool ok = true; - if (shouldDecode) { - ok = (fileRewindFun(info) == 0); - } - if (ok) { - return (GIF_OK); - } else { - info->gifFilePtr->Error = D_GIF_ERR_READ_FAILED; - return (GIF_ERROR); - } -} - -static void copyLine(argb *dst, const unsigned char *src, const ColorMapObject *cmap, int transparent, int width) { - for (; width > 0; width--, src++, dst++) { - if (*src != transparent) { - getColorFromTable(*src, dst, cmap); - } - } -} - -static argb *getAddr(argb *bm, int width, int left, int top) { - return bm + top * width + left; -} - -static void blitNormal(argb *bm, int width, int height, const SavedImage *frame, const ColorMapObject *cmap, int transparent) { - const unsigned char* src = (unsigned char*) frame->RasterBits; - argb *dst = getAddr(bm, width, frame->ImageDesc.Left, frame->ImageDesc.Top); - GifWord copyWidth = frame->ImageDesc.Width; - if (frame->ImageDesc.Left + copyWidth > width) { - copyWidth = width - frame->ImageDesc.Left; - } - - GifWord copyHeight = frame->ImageDesc.Height; - if (frame->ImageDesc.Top + copyHeight > height) { - copyHeight = height - frame->ImageDesc.Top; - } - - for (; copyHeight > 0; copyHeight--) { - copyLine(dst, src, cmap, transparent, copyWidth); - src += frame->ImageDesc.Width; - dst += width; - } -} - -static void fillRect(argb *bm, int bmWidth, int bmHeight, GifWord left, GifWord top, GifWord width, GifWord height, argb col) { - uint32_t* dst = (uint32_t*) getAddr(bm, bmWidth, left, top); - GifWord copyWidth = width; - if (left + copyWidth > bmWidth) { - copyWidth = bmWidth - left; - } - - GifWord copyHeight = height; - if (top + copyHeight > bmHeight) { - copyHeight = bmHeight - top; - } - uint32_t* pColor = (uint32_t *) (&col); - for (; copyHeight > 0; copyHeight--) { - memset(dst, *pColor, copyWidth * sizeof(argb)); - dst += bmWidth; - } -} - -static void drawFrame(argb *bm, int bmWidth, int bmHeight, const SavedImage *frame, const ColorMapObject *cmap, short transpIndex) { - if (frame->ImageDesc.ColorMap != NULL) { - cmap = frame->ImageDesc.ColorMap; - if (cmap->ColorCount != (1 << cmap->BitsPerPixel)) { - cmap = defaultCmap; - } - } - blitNormal(bm, bmWidth, bmHeight, frame, cmap, transpIndex); -} - -static bool checkIfCover(const SavedImage *target, const SavedImage *covered) { - if (target->ImageDesc.Left <= covered->ImageDesc.Left - && covered->ImageDesc.Left + covered->ImageDesc.Width - <= target->ImageDesc.Left + target->ImageDesc.Width - && target->ImageDesc.Top <= covered->ImageDesc.Top - && covered->ImageDesc.Top + covered->ImageDesc.Height - <= target->ImageDesc.Top + target->ImageDesc.Height) { - return true; - } - return false; -} - -static inline void disposeFrameIfNeeded(argb *bm, GifInfo *info, unsigned int idx) { - argb* backup = info->backupPtr; - argb color; - packARGB32(&color, 0, 0, 0, 0); - GifFileType *fGif = info->gifFilePtr; - SavedImage* cur = &fGif->SavedImages[idx - 1]; - SavedImage* next = &fGif->SavedImages[idx]; - bool curTrans = info->infos[idx - 1].transpIndex != -1; - int curDisposal = info->infos[idx - 1].disposalMethod; - bool nextTrans = info->infos[idx].transpIndex != -1; - int nextDisposal = info->infos[idx].disposalMethod; - argb *tmp; - if ((curDisposal == 2 || curDisposal == 3) && (nextTrans || !checkIfCover(next, cur))) { - switch (curDisposal) { - case 2: - - fillRect(bm, fGif->SWidth, fGif->SHeight, cur->ImageDesc.Left, cur->ImageDesc.Top, cur->ImageDesc.Width, cur->ImageDesc.Height, color); - break; - - case 3: - tmp = bm; - bm = backup; - backup = tmp; - break; - } - } - - if (nextDisposal == 3) { - memcpy(backup, bm, fGif->SWidth * fGif->SHeight * sizeof(argb)); - } -} - -static void reset(GifInfo *info) { - if (fileRewindFun(info) != 0) { - return; - } - info->nextStartTime = 0; - info->currentLoop = -1; - info->currentIndex = -1; -} - -static void getBitmap(argb *bm, GifInfo *info) { - GifFileType* fGIF = info->gifFilePtr; - - argb paintingColor; - int i = info->currentIndex; - if (DDGifSlurp(fGIF, info, true) == GIF_ERROR) { - return; - } - SavedImage* cur = &fGIF->SavedImages[i]; - int transpIndex = info->infos[i].transpIndex; - if (i == 0) { - if (transpIndex == -1) { - getColorFromTable(fGIF->SBackGroundColor, &paintingColor, fGIF->SColorMap); - } else { - packARGB32(&paintingColor, 0, 0, 0, 0); - } - eraseColor(bm, fGIF->SWidth, fGIF->SHeight, paintingColor); - } else { - disposeFrameIfNeeded(bm, info, i); - } - drawFrame(bm, fGIF->SWidth, fGIF->SHeight, cur, fGIF->SColorMap, transpIndex); -} - -static void setMetaData(int width, int height, int ImageCount, int errorCode, JNIEnv *env, jintArray metaData) { - jint *const ints = (*env)->GetIntArrayElements(env, metaData, 0); - if (ints == NULL) { - return; - } - ints[0] = width; - ints[1] = height; - ints[2] = ImageCount; - ints[3] = errorCode; - (*env)->ReleaseIntArrayElements(env, metaData, ints, 0); -} - -static jint open(GifFileType *GifFileIn, int Error, int startPos, JNIEnv *env, jintArray metaData) { - if (startPos < 0) { - Error = D_GIF_ERR_NOT_READABLE; - DGifCloseFile(GifFileIn); - } - if (Error != 0 || GifFileIn == NULL) { - setMetaData(0, 0, 0, Error, env, metaData); - return (jint) NULL; - } - int width = GifFileIn->SWidth, height = GifFileIn->SHeight; - unsigned int wxh = width * height; - if (wxh < 1 || wxh > INT_MAX) { - DGifCloseFile(GifFileIn); - setMetaData(width, height, 0, D_GIF_ERR_INVALID_SCR_DIMS, env, metaData); - return (jint) NULL; - } - GifInfo *info = malloc(sizeof(GifInfo)); - if (info == NULL) { - DGifCloseFile(GifFileIn); - setMetaData(width, height, 0, D_GIF_ERR_NOT_ENOUGH_MEM, env, metaData); - return (jint) NULL; - } - info->gifFilePtr = GifFileIn; - info->startPos = startPos; - info->currentIndex = -1; - info->nextStartTime = 0; - info->lastFrameReaminder = ULONG_MAX; - info->comment = NULL; - info->loopCount = 0; - info->currentLoop = -1; - info->speedFactor = 1.0; - info->rasterBits = calloc(GifFileIn->SHeight * GifFileIn->SWidth, sizeof(GifPixelType)); - info->infos = malloc(sizeof(FrameInfo)); - info->backupPtr = NULL; - - if (info->rasterBits == NULL || info->infos == NULL) { - cleanUp(info); - setMetaData(width, height, 0, D_GIF_ERR_NOT_ENOUGH_MEM, env, metaData); - return (jint) NULL; - } - info->infos->duration = 0; - info->infos->disposalMethod = 0; - info->infos->transpIndex = -1; - if (GifFileIn->SColorMap == NULL || GifFileIn->SColorMap->ColorCount != (1 << GifFileIn->SColorMap->BitsPerPixel)) { - GifFreeMapObject(GifFileIn->SColorMap); - GifFileIn->SColorMap = defaultCmap; - } - - DDGifSlurp(GifFileIn, info, false); - - int imgCount = GifFileIn->ImageCount; - - if (imgCount < 1) { - Error = D_GIF_ERR_NO_FRAMES; - } - if (fileRewindFun(info) != 0) { - Error = D_GIF_ERR_READ_FAILED; - } - if (Error != 0) { - cleanUp(info); - } - setMetaData(width, height, imgCount, Error, env, metaData); - return (jint)(Error == 0 ? info : NULL); -} - -JNIEXPORT jlong JNICALL Java_org_telegram_ui_Components_GifDrawable_getAllocationByteCount(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return 0; - } - unsigned int pxCount = info->gifFilePtr->SWidth + info->gifFilePtr->SHeight; - jlong sum = pxCount * sizeof(char); - if (info->backupPtr != NULL) { - sum += pxCount * sizeof(argb); - } - return sum; -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_reset(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return; - } - reset(info); -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_setSpeedFactor(JNIEnv *env, jclass class, jobject gifInfo, jfloat factor) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return; - } - info->speedFactor = factor; -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_seekToTime(JNIEnv *env, jclass class, jobject gifInfo, jint desiredPos, jintArray jPixels) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL || jPixels == NULL) { - return; - } - int imgCount = info->gifFilePtr->ImageCount; - if (imgCount <= 1) { - return; - } - - unsigned long sum = 0; - int i; - for (i = 0; i < imgCount; i++) { - unsigned long newSum = sum + info->infos[i].duration; - if (newSum >= desiredPos) { - break; - } - sum = newSum; - } - if (i < info->currentIndex) { - return; - } - - unsigned long lastFrameRemainder = desiredPos - sum; - if (i == imgCount - 1 && lastFrameRemainder > info->infos[i].duration) { - lastFrameRemainder = info->infos[i].duration; - } - if (i > info->currentIndex) { - jint *const pixels = (*env)->GetIntArrayElements(env, jPixels, 0); - if (pixels == NULL) { - return; - } - while (info->currentIndex <= i) { - info->currentIndex++; - getBitmap((argb*) pixels, info); - } - (*env)->ReleaseIntArrayElements(env, jPixels, pixels, 0); - } - info->lastFrameReaminder = lastFrameRemainder; - - if (info->speedFactor == 1.0) { - info->nextStartTime = getRealTime() + lastFrameRemainder; - } else { - info->nextStartTime = getRealTime() + lastFrameRemainder * info->speedFactor; - } -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_seekToFrame(JNIEnv *env, jclass class, jobject gifInfo, jint desiredIdx, jintArray jPixels) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL|| jPixels==NULL) { - return; - } - if (desiredIdx <= info->currentIndex) { - return; - } - - int imgCount = info->gifFilePtr->ImageCount; - if (imgCount <= 1) { - return; - } - - jint *const pixels = (*env)->GetIntArrayElements(env, jPixels, 0); - if (pixels == NULL) { - return; - } - - info->lastFrameReaminder = 0; - if (desiredIdx >= imgCount) { - desiredIdx = imgCount - 1; - } - - while (info->currentIndex < desiredIdx) { - info->currentIndex++; - getBitmap((argb *) pixels, info); - } - (*env)->ReleaseIntArrayElements(env, jPixels, pixels, 0); - if (info->speedFactor == 1.0) { - info->nextStartTime = getRealTime() + info->infos[info->currentIndex].duration; - } else { - info->nextStartTime = getRealTime() + info->infos[info->currentIndex].duration * info->speedFactor; - } -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_renderFrame(JNIEnv *env, jclass class, jintArray jPixels, jobject gifInfo, jintArray metaData) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL || jPixels == NULL) { - return; - } - bool needRedraw = false; - unsigned long rt = getRealTime(); - - if (rt >= info->nextStartTime && info->currentLoop < info->loopCount) { - if (++info->currentIndex >= info->gifFilePtr->ImageCount) { - info->currentIndex = 0; - } - needRedraw = true; - } - jint *const rawMetaData = (*env)->GetIntArrayElements(env, metaData, 0); - if (rawMetaData == NULL) { - return; - } - - if (needRedraw) { - jint *const pixels = (*env)->GetIntArrayElements(env, jPixels, 0); - if (pixels == NULL) { - (*env)->ReleaseIntArrayElements(env, metaData, rawMetaData, 0); - return; - } - getBitmap((argb *)pixels, info); - rawMetaData[3] = info->gifFilePtr->Error; - - (*env)->ReleaseIntArrayElements(env, jPixels, pixels, 0); - unsigned int scaledDuration = info->infos[info->currentIndex].duration; - if (info->speedFactor != 1.0) { - scaledDuration /= info->speedFactor; - if (scaledDuration<=0) { - scaledDuration=1; - } else if (scaledDuration > INT_MAX) { - scaledDuration = INT_MAX; - } - } - info->nextStartTime = rt + scaledDuration; - rawMetaData[4] = scaledDuration; - } else { - long delay = info->nextStartTime-rt; - if (delay < 0) { - rawMetaData[4] = -1; - } else { - rawMetaData[4] = (int) delay; - } - } - (*env)->ReleaseIntArrayElements(env, metaData, rawMetaData, 0); -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_free(JNIEnv *env, jclass class, jobject gifInfo) { - if (gifInfo == NULL) { - return; - } - GifInfo *info = (GifInfo *)gifInfo; - FILE *file = info->gifFilePtr->UserData; - if (file) { - fclose(file); - } - info->gifFilePtr->UserData = NULL; - cleanUp(info); -} - -JNIEXPORT jstring JNICALL Java_org_telegram_ui_Components_GifDrawable_getComment(JNIEnv *env, jclass class, jobject gifInfo) { - if (gifInfo == NULL) { - return NULL; - } - GifInfo *info = (GifInfo *)gifInfo; - return (*env)->NewStringUTF(env, info->comment); -} - -JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getLoopCount(JNIEnv *env, jclass class, jobject gifInfo) { - if (gifInfo == NULL) { - return 0; - } - return ((GifInfo *)gifInfo)->loopCount; -} - -JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getDuration(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return 0; - } - int i; - unsigned long sum = 0; - for (i = 0; i < info->gifFilePtr->ImageCount; i++) { - sum += info->infos[i].duration; - } - return sum; -} - -JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getCurrentPosition(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return 0; - } - int idx = info->currentIndex; - if (idx < 0 || info->gifFilePtr->ImageCount <= 1) { - return 0; - } - int i; - unsigned int sum = 0; - for (i = 0; i < idx; i++) { - sum += info->infos[i].duration; - } - unsigned long remainder = info->lastFrameReaminder == ULONG_MAX ? getRealTime() - info->nextStartTime : info->lastFrameReaminder; - return (int) (sum + remainder); -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_saveRemainder(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL) { - return; - } - info->lastFrameReaminder = getRealTime() - info->nextStartTime; -} - -JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_restoreRemainder(JNIEnv *env, jclass class, jobject gifInfo) { - GifInfo *info = (GifInfo *)gifInfo; - if (info == NULL || info->lastFrameReaminder == ULONG_MAX) { - return; - } - info->nextStartTime = getRealTime() + info->lastFrameReaminder; - info->lastFrameReaminder = ULONG_MAX; -} - -JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_openFile(JNIEnv *env, jclass class, jintArray metaData, jstring jfname) { - if (jfname == NULL) { - setMetaData(0, 0, 0, D_GIF_ERR_OPEN_FAILED, env, metaData); - return (jint) NULL; - } - - const char *const fname = (*env)->GetStringUTFChars(env, jfname, 0); - FILE *file = fopen(fname, "rb"); - (*env)->ReleaseStringUTFChars(env, jfname, fname); - if (file == NULL) { - setMetaData(0, 0, 0, D_GIF_ERR_OPEN_FAILED, env, metaData); - return (jint) NULL; - } - int Error = 0; - GifFileType *GifFileIn = DGifOpen(file, &fileReadFunc, &Error); - return open(GifFileIn, Error, ftell(file), env, metaData); -} diff --git a/TMessagesProj/jni/gif.h b/TMessagesProj/jni/gif.h deleted file mode 100644 index 96409be1..00000000 --- a/TMessagesProj/jni/gif.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef gif_h -#define gif_h - -jint gifOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env); -void gifOnJNIUnload(JavaVM *vm, void *reserved); - -#endif \ No newline at end of file diff --git a/TMessagesProj/jni/giflib/config.h b/TMessagesProj/jni/giflib/config.h deleted file mode 100644 index e68b0d9e..00000000 --- a/TMessagesProj/jni/giflib/config.h +++ /dev/null @@ -1,13 +0,0 @@ - -// giflib config.h - -#ifndef GIF_CONFIG_H_DEFINED -#define GIF_CONFIG_H_DEFINED - -#include -#define HAVE_STDINT_H -#define HAVE_FCNTL_H - -typedef uint32_t UINT32; - -#endif diff --git a/TMessagesProj/jni/giflib/dgif_lib.c b/TMessagesProj/jni/giflib/dgif_lib.c deleted file mode 100644 index 92442408..00000000 --- a/TMessagesProj/jni/giflib/dgif_lib.c +++ /dev/null @@ -1,1167 +0,0 @@ -/****************************************************************************** - -dgif_lib.c - GIF decoding - -The functions here and in egif_lib.c are partitioned carefully so that -if you only require one of read and write capability, only one of these -two modules will be linked. Preserve this property! - -*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#endif /* _WIN32 */ - -#include "gif_lib.h" -#include "gif_lib_private.h" - -/* compose unsigned little endian value */ -#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8)) - -/* avoid extra function call in case we use fread (TVT) */ -#define READ(_gif,_buf,_len) \ - (((GifFilePrivateType*)_gif->Private)->Read ? \ - ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ - fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File)) - -static int DGifGetWord(GifFileType *GifFile, GifWord *Word); -static int DGifSetupDecompress(GifFileType *GifFile); -static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, - int LineLen); -static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode); -static int DGifDecompressInput(GifFileType *GifFile, int *Code); -static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, - GifByteType *NextByte); - -/****************************************************************************** - Open a new GIF file for read, given by its name. - Returns dynamically allocated GifFileType pointer which serves as the GIF - info record. -******************************************************************************/ -GifFileType * -DGifOpenFileName(const char *FileName, int *Error) -{ - int FileHandle; - GifFileType *GifFile; - - if ((FileHandle = open(FileName, O_RDONLY)) == -1) { - if (Error != NULL) - *Error = D_GIF_ERR_OPEN_FAILED; - return NULL; - } - GifFile = DGifOpenFileHandle(FileHandle, Error); - return GifFile; -} - -/****************************************************************************** - Update a new GIF file, given its file handle. - Returns dynamically allocated GifFileType pointer which serves as the GIF - info record. -******************************************************************************/ -GifFileType * -DGifOpenFileHandle(int FileHandle, int *Error) -{ - char Buf[GIF_STAMP_LEN + 1]; - GifFileType *GifFile; - GifFilePrivateType *Private; - FILE *f; - - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; - (void)close(FileHandle); - return NULL; - } - - /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType)); - - /* Belt and suspenders, in case the null pointer isn't zero */ - GifFile->SavedImages = NULL; - GifFile->SColorMap = NULL; - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (Private == NULL) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; - (void)close(FileHandle); - free((char *)GifFile); - return NULL; - } -#ifdef _WIN32 - _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ -#endif /* _WIN32 */ - - f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ - - /*@-mustfreeonly@*/ - GifFile->Private = (void *)Private; - Private->FileHandle = FileHandle; - Private->File = f; - Private->FileState = FILE_STATE_READ; - Private->Read = NULL; /* don't use alternate input method (TVT) */ - GifFile->UserData = NULL; /* TVT */ - /*@=mustfreeonly@*/ - - /* Let's see if this is a GIF file: */ - if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - if (Error != NULL) - *Error = D_GIF_ERR_READ_FAILED; - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - /* Check for GIF prefix at start of file */ - Buf[GIF_STAMP_LEN] = 0; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_GIF_FILE; - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - GifFile->Error = 0; - - /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); - - return GifFile; -} - -/****************************************************************************** - GifFileType constructor with user supplied input function (TVT) -******************************************************************************/ -GifFileType * -DGifOpen(void *userData, InputFunc readFunc, int *Error) -{ - char Buf[GIF_STAMP_LEN + 1]; - GifFileType *GifFile; - GifFilePrivateType *Private; - - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - /* Belt and suspenders, in case the null pointer isn't zero */ - GifFile->SavedImages = NULL; - GifFile->SColorMap = NULL; - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (!Private) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; - free((char *)GifFile); - return NULL; - } - - GifFile->Private = (void *)Private; - Private->FileHandle = 0; - Private->File = NULL; - Private->FileState = FILE_STATE_READ; - - Private->Read = readFunc; /* TVT */ - GifFile->UserData = userData; /* TVT */ - - /* Lets see if this is a GIF file: */ - if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - if (Error != NULL) - *Error = D_GIF_ERR_READ_FAILED; - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - /* Check for GIF prefix at start of file */ - Buf[GIF_STAMP_LEN] = '\0'; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) - *Error = D_GIF_ERR_NOT_GIF_FILE; - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - free((char *)Private); - free((char *)GifFile); - *Error = D_GIF_ERR_NO_SCRN_DSCR; - return NULL; - } - - GifFile->Error = 0; - - /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); - - return GifFile; -} - -/****************************************************************************** - This routine should be called before any other DGif calls. Note that - this routine is called automatically from DGif file open routines. -******************************************************************************/ -int -DGifGetScreenDesc(GifFileType *GifFile) -{ - int BitsPerPixel; - bool SortFlag; - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - /* Put the screen descriptor into the file: */ - if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) - return GIF_ERROR; - - if (READ(GifFile, Buf, 3) != 3) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - return GIF_ERROR; - } - GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; - SortFlag = (Buf[0] & 0x08) != 0; - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->SBackGroundColor = Buf[1]; - GifFile->AspectByte = Buf[2]; - if (Buf[0] & 0x80) { /* Do we have global color map? */ - int i; - - GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->SColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - - /* Get the global color map: */ - GifFile->SColorMap->SortFlag = SortFlag; - for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { - if (READ(GifFile, Buf, 3) != 3) { - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - GifFile->SColorMap->Colors[i].Red = Buf[0]; - GifFile->SColorMap->Colors[i].Green = Buf[1]; - GifFile->SColorMap->Colors[i].Blue = Buf[2]; - } - } else { - GifFile->SColorMap = NULL; - } - - return GIF_OK; -} - -/****************************************************************************** - This routine should be called before any attempt to read an image. -******************************************************************************/ -int -DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (READ(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - switch (Buf) { - case DESCRIPTOR_INTRODUCER: - *Type = IMAGE_DESC_RECORD_TYPE; - break; - case EXTENSION_INTRODUCER: - *Type = EXTENSION_RECORD_TYPE; - break; - case TERMINATOR_INTRODUCER: - *Type = TERMINATE_RECORD_TYPE; - break; - default: - *Type = UNDEFINED_RECORD_TYPE; - GifFile->Error = D_GIF_ERR_WRONG_RECORD; - return GIF_ERROR; - } - - return GIF_OK; -} - -/****************************************************************************** - This routine should be called before any attempt to read an image. - Note it is assumed the Image desc. header has been read. -******************************************************************************/ -int -DGifGetImageDesc(GifFileType *GifFile, bool changeImageCount) -{ - unsigned int BitsPerPixel; - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - SavedImage *sp; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) - return GIF_ERROR; - if (READ(GifFile, Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - return GIF_ERROR; - } - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; - - /* Setup the colormap */ - if (GifFile->Image.ColorMap) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - /* Does this image have local color map? */ - if (Buf[0] & 0x80) { - unsigned int i; - - GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->Image.ColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - - /* Get the image local color map: */ - for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { - if (READ(GifFile, Buf, 3) != 3) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Error = D_GIF_ERR_READ_FAILED; - GifFile->Image.ColorMap = NULL; - return GIF_ERROR; - } - GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; - GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; - GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; - } - } - // if (changeImageCount) - { - if (GifFile->SavedImages) { - if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, - sizeof(SavedImage) * - (GifFile->ImageCount + 1))) == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } else { - if ((GifFile->SavedImages = - (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } - } - sp = &GifFile->SavedImages[GifFile->ImageCount]; - memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); - if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = GifMakeMapObject( - GifFile->Image.ColorMap->ColorCount, - GifFile->Image.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } - sp->RasterBits = (unsigned char *)NULL; - sp->ExtensionBlockCount = 0; - sp->ExtensionBlocks = (ExtensionBlock *) NULL; - if (changeImageCount) - GifFile->ImageCount++; - - Private->PixelCount = (long)GifFile->Image.Width * - (long)GifFile->Image.Height; - - /* Reset decompress algorithm parameters. */ - (void)DGifSetupDecompress(GifFile); - - return GIF_OK; -} - -/****************************************************************************** - Get one full scanned line (Line) of length LineLen from GIF file. -******************************************************************************/ -int -DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) -{ - GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (!LineLen) - LineLen = GifFile->Image.Width; - - if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { - GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - - if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { - if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean up - * everything before we return: need to flush out all the - * rest of image until an empty block (size 0) - * detected. We use GetCodeNext. - */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) - return GIF_ERROR; - while (Dummy != NULL) ; - } - return GIF_OK; - } else - return GIF_ERROR; -} - -/****************************************************************************** - Put one pixel (Pixel) into GIF file. -******************************************************************************/ -int -DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) -{ - GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - if (--Private->PixelCount > 0xffff0000UL) - { - GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - - if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { - if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean up - * everything before we return: need to flush out all the - * rest of image until an empty block (size 0) - * detected. We use GetCodeNext. - */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) - return GIF_ERROR; - while (Dummy != NULL) ; - } - return GIF_OK; - } else - return GIF_ERROR; -} - -/****************************************************************************** - Get an extension block (see GIF manual) from GIF file. This routine only - returns the first data block, and DGifGetExtensionNext should be called - after this one until NULL extension is returned. - The Extension should NOT be freed by the user (not dynamically allocated). - Note it is assumed the Extension description header has been read. -******************************************************************************/ -int -DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (READ(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *ExtCode = Buf; - - return DGifGetExtensionNext(GifFile, Extension, ExtCode); -} - -/****************************************************************************** - Get a following extension block (see GIF manual) from GIF file. This - routine should be called until NULL Extension is returned. - The Extension should NOT be freed by the user (not dynamically allocated). -******************************************************************************/ -int -DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension, int* ExtCode) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (READ(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - if (Buf > 0) - { - if (*ExtCode==GRAPHICS_EXT_FUNC_CODE) - Buf=4; - *Extension = Private->Buf; /* Use private unused buffer. */ - (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data] */ - if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - } else - *Extension = NULL; - - return GIF_OK; -} - -/****************************************************************************** - Extract a Graphics Control Block from raw extension data -******************************************************************************/ - -int DGifExtensionToGCB(const size_t GifExtensionLength, - const GifByteType *GifExtension, - GraphicsControlBlock *GCB) -{ - if (GifExtensionLength != 4) { - return GIF_ERROR; - } - - GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; - GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; - GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); - if (GifExtension[0] & 0x01) - GCB->TransparentColor = (int)GifExtension[3]; - else - GCB->TransparentColor = NO_TRANSPARENT_COLOR; - - return GIF_OK; -} - -/****************************************************************************** - Extract the Graphics Control Block for a saved image, if it exists. -******************************************************************************/ - -int DGifSavedExtensionToGCB(GifFileType *GifFile, - int ImageIndex, GraphicsControlBlock *GCB) -{ - int i; - - if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) - return GIF_ERROR; - - GCB->DisposalMode = DISPOSAL_UNSPECIFIED; - GCB->UserInputFlag = false; - GCB->DelayTime = 0; - GCB->TransparentColor = NO_TRANSPARENT_COLOR; - - for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { - ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; - if (ep->Function == GRAPHICS_EXT_FUNC_CODE) - return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB); - } - - return GIF_ERROR; -} - -/****************************************************************************** - This routine should be called last, to close the GIF file. -******************************************************************************/ -int -DGifCloseFile(GifFileType *GifFile) -{ - GifFilePrivateType *Private; - - if (GifFile == NULL || GifFile->Private == NULL) - return GIF_ERROR; - - if (GifFile->Image.ColorMap) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - - if (GifFile->SColorMap) { - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - } - - if (GifFile->SavedImages) { - GifFreeSavedImages(GifFile); - GifFile->SavedImages = NULL; - } - - GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks); - - Private = (GifFilePrivateType *) GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (Private->File && (fclose(Private->File) != 0)) { - GifFile->Error = D_GIF_ERR_CLOSE_FAILED; - return GIF_ERROR; - } - - free((char *)GifFile->Private); - - /* - * Without the #ifndef, we get spurious warnings because Coverity mistakenly - * thinks the GIF structure is freed on an error return. - */ -#ifndef __COVERITY__ - free(GifFile); -#endif /* __COVERITY__ */ - - return GIF_OK; -} - -/****************************************************************************** - Get 2 bytes (word) from the given file: -******************************************************************************/ -static int -DGifGetWord(GifFileType *GifFile, GifWord *Word) -{ - unsigned char c[2]; - - if (READ(GifFile, c, 2) != 2) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); - return GIF_OK; -} - -/****************************************************************************** - Get the image code in compressed form. This routine can be called if the - information needed to be piped out as is. Obviously this is much faster - than decoding and encoding again. This routine should be followed by calls - to DGifGetCodeNext, until NULL block is returned. - The block should NOT be freed by the user (not dynamically allocated). -******************************************************************************/ -int -DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) -{ - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - *CodeSize = Private->BitsPerPixel; - - return DGifGetCodeNext(GifFile, CodeBlock); -} - -/****************************************************************************** - Continue to get the image code in compressed form. This routine should be - called until NULL block is returned. - The block should NOT be freed by the user (not dynamically allocated). -******************************************************************************/ -int -DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - /* coverity[tainted_data_argument] */ - if (READ(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - /* coverity[lower_bounds] */ - if (Buf > 0) { - *CodeBlock = Private->Buf; /* Use private unused buffer. */ - (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data] */ - if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - } else { - *CodeBlock = NULL; - Private->Buf[0] = 0; /* Make sure the buffer is empty! */ - Private->PixelCount = 0; /* And local info. indicate image read. */ - } - - return GIF_OK; -} - -/****************************************************************************** - Setup the LZ decompression for this image: -******************************************************************************/ -static int -DGifSetupDecompress(GifFileType *GifFile) -{ - int i, BitsPerPixel; - GifByteType CodeSize; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ - BitsPerPixel = CodeSize; - - Private->Buf[0] = 0; /* Input Buffer empty. */ - Private->BitsPerPixel = BitsPerPixel; - Private->ClearCode = (1 << BitsPerPixel); - Private->EOFCode = Private->ClearCode + 1; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ - Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ - Private->StackPtr = 0; /* No pixels on the pixel stack. */ - Private->LastCode = NO_SUCH_CODE; - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ - Private->CrntShiftDWord = 0; - - Prefix = Private->Prefix; - for (i = 0; i <= LZ_MAX_CODE; i++) - Prefix[i] = NO_SUCH_CODE; - - return GIF_OK; -} - -/****************************************************************************** - The LZ decompression routine: - This version decompress the given GIF file into Line of length LineLen. - This routine can be called few times (one per scan line, for example), in - order the complete the whole image. -******************************************************************************/ -static int -DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) -{ - int i = 0; - int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; - GifByteType *Stack, *Suffix; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - StackPtr = Private->StackPtr; - Prefix = Private->Prefix; - Suffix = Private->Suffix; - Stack = Private->Stack; - EOFCode = Private->EOFCode; - ClearCode = Private->ClearCode; - LastCode = Private->LastCode; - - if (StackPtr > LZ_MAX_CODE) { - return GIF_ERROR; - } - - if (StackPtr != 0) { - /* Let pop the stack off before continueing to read the GIF file: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - - while (i < LineLen) { /* Decode LineLen items. */ - if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) - return GIF_ERROR; - - if (CrntCode == EOFCode) { - /* Note however that usually we will not be here as we will stop - * decoding as soon as we got all the pixel, or EOF code will - * not be read at all, and DGifGetLine/Pixel clean everything. */ - GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; - return GIF_ERROR; - } else if (CrntCode == ClearCode) { - /* We need to start over again: */ - for (j = 0; j <= LZ_MAX_CODE; j++) - Prefix[j] = NO_SUCH_CODE; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - LastCode = Private->LastCode = NO_SUCH_CODE; - } else { - /* Its regular code - if in pixel range simply add it to output - * stream, otherwise trace to codes linked list until the prefix - * is in pixel range: */ - if (CrntCode < ClearCode) { - /* This is simple - its pixel scalar, so add it to output: */ - Line[i++] = CrntCode; - } else { - /* Its a code to needed to be traced: trace the linked list - * until the prefix is a pixel, while pushing the suffix - * pixels on our stack. If we done, pop the stack in reverse - * (thats what stack is good for!) order to output. */ - if (Prefix[CrntCode] == NO_SUCH_CODE) { - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ - if (CrntCode == Private->RunningCode - 2) { - CrntPrefix = LastCode; - Suffix[Private->RunningCode - 2] = - Stack[StackPtr++] = DGifGetPrefixChar(Prefix, - LastCode, - ClearCode); - } else { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - } else - CrntPrefix = CrntCode; - - /* Now (if image is O.K.) we should not get a NO_SUCH_CODE - * during the trace. As we might loop forever, in case of - * defective image, we use StackPtr as loop counter and stop - * before overflowing Stack[]. */ - while (StackPtr < LZ_MAX_CODE && - CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { - Stack[StackPtr++] = Suffix[CrntPrefix]; - CrntPrefix = Prefix[CrntPrefix]; - } - if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - /* Push the last character on stack: */ - Stack[StackPtr++] = CrntPrefix; - - /* Now lets pop all the stack into output: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { - Prefix[Private->RunningCode - 2] = LastCode; - - if (CrntCode == Private->RunningCode - 2) { - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, LastCode, ClearCode); - } else { - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, CrntCode, ClearCode); - } - } - LastCode = CrntCode; - } - } - - Private->LastCode = LastCode; - Private->StackPtr = StackPtr; - - return GIF_OK; -} - -/****************************************************************************** - Routine to trace the Prefixes linked list until we get a prefix which is - not code, but a pixel value (less than ClearCode). Returns that pixel value. - If image is defective, we might loop here forever, so we limit the loops to - the maximum possible if image O.k. - LZ_MAX_CODE times. -******************************************************************************/ -static int -DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) -{ - int i = 0; - - while (Code > ClearCode && i++ <= LZ_MAX_CODE) { - if (Code > LZ_MAX_CODE) { - return NO_SUCH_CODE; - } - Code = Prefix[Code]; - } - return Code; -} - -/****************************************************************************** - Interface for accessing the LZ codes directly. Set Code to the real code - (12bits), or to -1 if EOF code is returned. -******************************************************************************/ -int -DGifGetLZCodes(GifFileType *GifFile, int *Code) -{ - GifByteType *CodeBlock; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) - return GIF_ERROR; - - if (*Code == Private->EOFCode) { - /* Skip rest of codes (hopefully only NULL terminating block): */ - do { - if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) - return GIF_ERROR; - } while (CodeBlock != NULL) ; - - *Code = -1; - } else if (*Code == Private->ClearCode) { - /* We need to start over again: */ - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - } - - return GIF_OK; -} - -/****************************************************************************** - The LZ decompression input routine: - This routine is responsable for the decompression of the bit stream from - 8 bits (bytes) packets, into the real codes. - Returns GIF_OK if read successfully. -******************************************************************************/ -static int -DGifDecompressInput(GifFileType *GifFile, int *Code) -{ - static const unsigned short CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000f, 0x001f, 0x003f, 0x007f, - 0x00ff, 0x01ff, 0x03ff, 0x07ff, - 0x0fff - }; - - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - GifByteType NextByte; - - /* The image can't contain more than LZ_BITS per code. */ - if (Private->RunningBits > LZ_BITS) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - - while (Private->CrntShiftState < Private->RunningBits) { - /* Needs to get more bytes from input stream for next code: */ - if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { - return GIF_ERROR; - } - Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; - Private->CrntShiftState += 8; - } - *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; - - Private->CrntShiftDWord >>= Private->RunningBits; - Private->CrntShiftState -= Private->RunningBits; - - /* If code cannot fit into RunningBits bits, must raise its size. Note - * however that codes above 4095 are used for special signaling. - * If we're using LZ_BITS bits already and we're at the max code, just - * keep using the table as it is, don't increment Private->RunningCode. - */ - if (Private->RunningCode < LZ_MAX_CODE + 2 && - ++Private->RunningCode > Private->MaxCode1 && - Private->RunningBits < LZ_BITS) { - Private->MaxCode1 <<= 1; - Private->RunningBits++; - } - return GIF_OK; -} - -/****************************************************************************** - This routines read one GIF data block at a time and buffers it internally - so that the decompression routine could access it. - The routine returns the next byte from its internal buffer (or read next - block in if buffer empty) and returns GIF_OK if succesful. -******************************************************************************/ -static int -DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) -{ - if (Buf[0] == 0) { - /* Needs to read the next buffer - this one is empty: */ - if (READ(GifFile, Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore we - * shouldn't be inside this routine at that point. - */ - if (Buf[0] == 0) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore we - * shouldn't be inside this routine at that point. - */ - if (Buf[0] == 0) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *NextByte = Buf[1]; - Buf[1] = 2; /* We use now the second place as last char read! */ - Buf[0]--; - } else { - *NextByte = Buf[Buf[1]++]; - Buf[0]--; - } - - return GIF_OK; -} - -/****************************************************************************** - This routine reads an entire GIF into core, hanging all its state info off - the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() - first to initialize I/O. Its inverse is EGifSpew(). - -int -DGifSlurp(GifFileType *GifFile) -{ - size_t ImageSize; - GifRecordType RecordType; - SavedImage *sp; - GifByteType *ExtData; - int ExtFunction; - - GifFile->ExtensionBlocks = NULL; - GifFile->ExtensionBlockCount = 0; - - do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) - return (GIF_ERROR); - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(GifFile) == GIF_ERROR) - return (GIF_ERROR); - - sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; - if (GifFile->ExtensionBlocks) { - sp->ExtensionBlocks = GifFile->ExtensionBlocks; - sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; - - GifFile->ExtensionBlocks = NULL; - GifFile->ExtensionBlockCount = 0; - } - // Allocate memory for the image - if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 && - sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { - return GIF_ERROR; - } - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { - return GIF_ERROR; - } - sp->RasterBits = (unsigned char *)malloc(ImageSize * - sizeof(GifPixelType)); - - if (sp->RasterBits == NULL) { - return GIF_ERROR; - } - - if (sp->ImageDesc.Interlace) - { - int i, j; - // The way an interlaced image should be read - * offsets and jumps... - - int InterlacedOffset[] = { 0, 4, 2, 1 }; - int InterlacedJumps[] = { 8, 8, 4, 2 }; - // Need to perform 4 passes on the image - for (i = 0; i < 4; i++) - for (j = InterlacedOffset[i]; - j < sp->ImageDesc.Height; - j += InterlacedJumps[i]) { - if (DGifGetLine(GifFile, - sp->RasterBits+j*sp->ImageDesc.Width, - sp->ImageDesc.Width) == GIF_ERROR) - return GIF_ERROR; - } - } - else - { - if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) - return (GIF_ERROR); - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) - return (GIF_ERROR); - // Create an extension block with our data - if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - ExtFunction, ExtData[0], &ExtData[1]) - == GIF_ERROR) - return (GIF_ERROR); - while (ExtData != NULL) { - if (DGifGetExtensionNext(GifFile, &ExtData, &ExtFunction) == GIF_ERROR) - return (GIF_ERROR); - // Continue the extension block / - if (ExtData != NULL) - if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - CONTINUE_EXT_FUNC_CODE, - ExtData[0], &ExtData[1]) == GIF_ERROR) - return (GIF_ERROR); - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: // Should be trapped by DGifGetRecordType - break; - } - } while (RecordType != TERMINATE_RECORD_TYPE); - - return (GIF_OK); -} - - end */ diff --git a/TMessagesProj/jni/giflib/gif_hash.c b/TMessagesProj/jni/giflib/gif_hash.c deleted file mode 100644 index 61a4d139..00000000 --- a/TMessagesProj/jni/giflib/gif_hash.c +++ /dev/null @@ -1,132 +0,0 @@ -/***************************************************************************** - -gif_hash.c -- module to support the following operations: - -1. InitHashTable - initialize hash table. -2. ClearHashTable - clear the hash table to an empty state. -2. InsertHashTable - insert one item into data structure. -3. ExistsHashTable - test if item exists in data structure. - -This module is used to hash the GIF codes during encoding. - -*****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "gif_lib.h" -#include "gif_hash.h" -#include "gif_lib_private.h" - -/* #define DEBUG_HIT_RATE Debug number of misses per hash Insert/Exists. */ - -#ifdef DEBUG_HIT_RATE -static long NumberOfTests = 0, - NumberOfMisses = 0; -#endif /* DEBUG_HIT_RATE */ - -static int KeyItem(uint32_t Item); - -/****************************************************************************** - Initialize HashTable - allocate the memory needed and clear it. * -******************************************************************************/ -GifHashTableType *_InitHashTable(void) -{ - GifHashTableType *HashTable; - - if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType))) - == NULL) - return NULL; - - _ClearHashTable(HashTable); - - return HashTable; -} - -/****************************************************************************** - Routine to clear the HashTable to an empty state. * - This part is a little machine depended. Use the commented part otherwise. * -******************************************************************************/ -void _ClearHashTable(GifHashTableType *HashTable) -{ - memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(uint32_t)); -} - -/****************************************************************************** - Routine to insert a new Item into the HashTable. The data is assumed to be * - new one. * -******************************************************************************/ -void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code) -{ - int HKey = KeyItem(Key); - uint32_t *HTable = HashTable -> HTable; - -#ifdef DEBUG_HIT_RATE - NumberOfTests++; - NumberOfMisses++; -#endif /* DEBUG_HIT_RATE */ - - while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) { -#ifdef DEBUG_HIT_RATE - NumberOfMisses++; -#endif /* DEBUG_HIT_RATE */ - HKey = (HKey + 1) & HT_KEY_MASK; - } - HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code); -} - -/****************************************************************************** - Routine to test if given Key exists in HashTable and if so returns its code * - Returns the Code if key was found, -1 if not. * -******************************************************************************/ -int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key) -{ - int HKey = KeyItem(Key); - uint32_t *HTable = HashTable -> HTable, HTKey; - -#ifdef DEBUG_HIT_RATE - NumberOfTests++; - NumberOfMisses++; -#endif /* DEBUG_HIT_RATE */ - - while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) { -#ifdef DEBUG_HIT_RATE - NumberOfMisses++; -#endif /* DEBUG_HIT_RATE */ - if (Key == HTKey) return HT_GET_CODE(HTable[HKey]); - HKey = (HKey + 1) & HT_KEY_MASK; - } - - return -1; -} - -/****************************************************************************** - Routine to generate an HKey for the hashtable out of the given unique key. * - The given Key is assumed to be 20 bits as follows: lower 8 bits are the * - new postfix character, while the upper 12 bits are the prefix code. * - Because the average hit ratio is only 2 (2 hash references per entry), * - evaluating more complex keys (such as twin prime keys) does not worth it! * -******************************************************************************/ -static int KeyItem(uint32_t Item) -{ - return ((Item >> 12) ^ Item) & HT_KEY_MASK; -} - -#ifdef DEBUG_HIT_RATE -/****************************************************************************** - Debugging routine to print the hit ratio - number of times the hash table * - was tested per operation. This routine was used to test the KeyItem routine * -******************************************************************************/ -void HashTablePrintHitRatio(void) -{ - printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n", - NumberOfMisses, NumberOfTests, - NumberOfMisses * 100 / NumberOfTests); -} -#endif /* DEBUG_HIT_RATE */ - -/* end */ diff --git a/TMessagesProj/jni/giflib/gif_hash.h b/TMessagesProj/jni/giflib/gif_hash.h deleted file mode 100644 index ac20a43c..00000000 --- a/TMessagesProj/jni/giflib/gif_hash.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - -gif_hash.h - magfic constants and declarations for GIF LZW - -******************************************************************************/ - -#ifndef _GIF_HASH_H_ -#define _GIF_HASH_H_ - -#include -#include - -#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */ -#define HT_KEY_MASK 0x1FFF /* 13bits keys */ -#define HT_KEY_NUM_BITS 13 /* 13bits keys */ -#define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */ -#define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ - -/* The 32 bits of the long are divided into two parts for the key & code: */ -/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */ -/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ -/* The key is the upper 20 bits. The code is the lower 12. */ -#define HT_GET_KEY(l) (l >> 12) -#define HT_GET_CODE(l) (l & 0x0FFF) -#define HT_PUT_KEY(l) (l << 12) -#define HT_PUT_CODE(l) (l & 0x0FFF) - -typedef struct GifHashTableType { - uint32_t HTable[HT_SIZE]; -} GifHashTableType; - -GifHashTableType *_InitHashTable(void); -void _ClearHashTable(GifHashTableType *HashTable); -void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code); -int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key); - -#endif /* _GIF_HASH_H_ */ - -/* end */ diff --git a/TMessagesProj/jni/giflib/gif_lib.h b/TMessagesProj/jni/giflib/gif_lib.h deleted file mode 100644 index b7aa9301..00000000 --- a/TMessagesProj/jni/giflib/gif_lib.h +++ /dev/null @@ -1,307 +0,0 @@ -/****************************************************************************** - -gif_lib.h - service library for decoding and encoding GIF images - -*****************************************************************************/ - -#ifndef _GIF_LIB_H_ -#define _GIF_LIB_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define GIFLIB_MAJOR 5 -#define GIFLIB_MINOR 0 -#define GIFLIB_RELEASE 5 - -#define GIF_ERROR 0 -#define GIF_OK 1 - -#include -#include - -#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ -#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 -#define GIF_VERSION_POS 3 /* Version first character in stamp. */ -#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */ -#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */ - -typedef unsigned char GifPixelType; -typedef unsigned char *GifRowType; -typedef unsigned char GifByteType; -typedef unsigned int GifPrefixType; -typedef int GifWord; - -typedef struct GifColorType { - GifByteType Red, Green, Blue; -} GifColorType; - -typedef struct ColorMapObject { - int ColorCount; - int BitsPerPixel; - bool SortFlag; - GifColorType *Colors; /* on malloc(3) heap */ -} ColorMapObject; - -typedef struct GifImageDesc { - GifWord Left, Top, Width, Height; /* Current image dimensions. */ - bool Interlace; /* Sequential/Interlaced lines. */ - ColorMapObject *ColorMap; /* The local color map */ -} GifImageDesc; - -typedef struct ExtensionBlock { - int ByteCount; - GifByteType *Bytes; /* on malloc(3) heap */ - int Function; /* The block function code */ -#define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ -#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ -#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ -#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ -#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ -} ExtensionBlock; - -typedef struct SavedImage { - GifImageDesc ImageDesc; - GifByteType *RasterBits; /* on malloc(3) heap */ - int ExtensionBlockCount; /* Count of extensions before image */ - ExtensionBlock *ExtensionBlocks; /* Extensions before image */ -} SavedImage; - -typedef struct GifFileType { - GifWord SWidth, SHeight; /* Size of virtual canvas */ - GifWord SColorResolution; /* How many colors can we generate? */ - GifWord SBackGroundColor; /* Background color for virtual canvas */ - GifByteType AspectByte; /* Used to compute pixel aspect ratio */ - ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ - int ImageCount; /* Number of current image (both APIs) */ - GifImageDesc Image; /* Current image (low-level API) */ - SavedImage *SavedImages; /* Image sequence (high-level API) */ - int ExtensionBlockCount; /* Count extensions past last image */ - ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ - int Error; /* Last error condition reported */ - void *UserData; /* hook to attach user data (TVT) */ - void *Private; /* Don't mess with this! */ -} GifFileType; - -#define GIF_ASPECT_RATIO(n) ((n)+15.0/64.0) - -typedef enum { - UNDEFINED_RECORD_TYPE, - SCREEN_DESC_RECORD_TYPE, - IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ - EXTENSION_RECORD_TYPE, /* Begin with '!' */ - TERMINATE_RECORD_TYPE /* Begin with ';' */ -} GifRecordType; - -/* func type to read gif data from arbitrary sources (TVT) */ -typedef int (*InputFunc) (GifFileType *, GifByteType *, int); - -/* func type to write gif data to arbitrary targets. - * Returns count of bytes written. (MRB) - */ -typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int); - -/****************************************************************************** - GIF89 structures -******************************************************************************/ - -typedef struct GraphicsControlBlock { - int DisposalMode; -#define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ -#define DISPOSE_DO_NOT 1 /* Leave image in place */ -#define DISPOSE_BACKGROUND 2 /* Set area too background color */ -#define DISPOSE_PREVIOUS 3 /* Restore to previous content */ - bool UserInputFlag; /* User confirmation required before disposal */ - int DelayTime; /* pre-display delay in 0.01sec units */ - int TransparentColor; /* Palette index for transparency, -1 if none */ -#define NO_TRANSPARENT_COLOR -1 -} GraphicsControlBlock; - -/****************************************************************************** - GIF encoding routines -******************************************************************************/ - -/* Main entry points */ -GifFileType *EGifOpenFileName(const char *GifFileName, - const bool GifTestExistence, int *Error); -GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error); -GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error); -int EGifSpew(GifFileType * GifFile); -char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ -int EGifCloseFile(GifFileType * GifFile); - -#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ -#define E_GIF_ERR_WRITE_FAILED 2 -#define E_GIF_ERR_HAS_SCRN_DSCR 3 -#define E_GIF_ERR_HAS_IMAG_DSCR 4 -#define E_GIF_ERR_NO_COLOR_MAP 5 -#define E_GIF_ERR_DATA_TOO_BIG 6 -#define E_GIF_ERR_NOT_ENOUGH_MEM 7 -#define E_GIF_ERR_DISK_IS_FULL 8 -#define E_GIF_ERR_CLOSE_FAILED 9 -#define E_GIF_ERR_NOT_WRITEABLE 10 - -/* These are legacy. You probably do not want to call them directly */ -int EGifPutScreenDesc(GifFileType *GifFile, - const int GifWidth, const int GifHeight, - const int GifColorRes, - const int GifBackGround, - const ColorMapObject *GifColorMap); -int EGifPutImageDesc(GifFileType *GifFile, - const int GifLeft, const int GifTop, - const int GifWidth, const int GifHeight, - const bool GifInterlace, - const ColorMapObject *GifColorMap); -void EGifSetGifVersion(GifFileType *GifFile, const bool gif89); -int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, - int GifLineLen); -int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel); -int EGifPutComment(GifFileType *GifFile, const char *GifComment); -int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode); -int EGifPutExtensionBlock(GifFileType *GifFile, - const int GifExtLen, const void *GifExtension); -int EGifPutExtensionTrailer(GifFileType *GifFile); -int EGifPutExtension(GifFileType *GifFile, const int GifExtCode, - const int GifExtLen, - const void *GifExtension); -int EGifPutCode(GifFileType *GifFile, int GifCodeSize, - const GifByteType *GifCodeBlock); -int EGifPutCodeNext(GifFileType *GifFile, - const GifByteType *GifCodeBlock); - -/****************************************************************************** - GIF decoding routines -******************************************************************************/ - -/* Main entry points */ -GifFileType *DGifOpenFileName(const char *GifFileName, int *Error); -GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error); -int DGifSlurp(GifFileType * GifFile); -GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */ -int DGifCloseFile(GifFileType * GifFile); - -#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ -#define D_GIF_ERR_READ_FAILED 102 -#define D_GIF_ERR_NOT_GIF_FILE 103 -#define D_GIF_ERR_NO_SCRN_DSCR 104 -#define D_GIF_ERR_NO_IMAG_DSCR 105 -#define D_GIF_ERR_NO_COLOR_MAP 106 -#define D_GIF_ERR_WRONG_RECORD 107 -#define D_GIF_ERR_DATA_TOO_BIG 108 -#define D_GIF_ERR_NOT_ENOUGH_MEM 109 -#define D_GIF_ERR_CLOSE_FAILED 110 -#define D_GIF_ERR_NOT_READABLE 111 -#define D_GIF_ERR_IMAGE_DEFECT 112 -#define D_GIF_ERR_EOF_TOO_SOON 113 - -/* These are legacy. You probably do not want to call them directly */ -int DGifGetScreenDesc(GifFileType *GifFile); -int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType); -int DGifGetImageDesc(GifFileType *GifFile, bool changeImageCount); -int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen); -int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel); -int DGifGetComment(GifFileType *GifFile, char *GifComment); -int DGifGetExtension(GifFileType *GifFile, int *GifExtCode, - GifByteType **GifExtension); -int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension,int* ExtCode); -int DGifGetCode(GifFileType *GifFile, int *GifCodeSize, - GifByteType **GifCodeBlock); -int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock); -int DGifGetLZCodes(GifFileType *GifFile, int *GifCode); - - -/****************************************************************************** - Color table quantization (deprecated) -******************************************************************************/ -int GifQuantizeBuffer(unsigned int Width, unsigned int Height, - int *ColorMapSize, GifByteType * RedInput, - GifByteType * GreenInput, GifByteType * BlueInput, - GifByteType * OutputBuffer, - GifColorType * OutputColorMap); - -/****************************************************************************** - Error handling and reporting. -******************************************************************************/ -extern char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ - -/***************************************************************************** - Everything below this point is new after version 1.2, supporting `slurp - mode' for doing I/O in two big belts with all the image-bashing in core. -******************************************************************************/ - -/****************************************************************************** - Color map handling from gif_alloc.c -******************************************************************************/ - -extern ColorMapObject *GifMakeMapObject(int ColorCount, - const GifColorType *ColorMap); -extern void GifFreeMapObject(ColorMapObject *Object); -extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, - const ColorMapObject *ColorIn2, - GifPixelType ColorTransIn2[]); -extern int GifBitSize(int n); - -/****************************************************************************** - Support for the in-core structures allocation (slurp mode). -******************************************************************************/ - -extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]); -extern int GifAddExtensionBlock(int *ExtensionBlock_Count, - ExtensionBlock **ExtensionBlocks, - int Function, - unsigned int Len, unsigned char ExtData[]); -extern void GifFreeExtensions(int *ExtensionBlock_Count, - ExtensionBlock **ExtensionBlocks); -extern SavedImage *GifMakeSavedImage(GifFileType *GifFile, - const SavedImage *CopyFrom); -extern void GifFreeSavedImages(GifFileType *GifFile); - -/****************************************************************************** - 5.x functions for GIF89 graphics control blocks -******************************************************************************/ - -int DGifExtensionToGCB(const size_t GifExtensionLength, - const GifByteType *GifExtension, - GraphicsControlBlock *GCB); -size_t EGifGCBToExtension(const GraphicsControlBlock *GCB, - GifByteType *GifExtension); - -int DGifSavedExtensionToGCB(GifFileType *GifFile, - int ImageIndex, - GraphicsControlBlock *GCB); -int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, - GifFileType *GifFile, - int ImageIndex); - -/****************************************************************************** - The library's internal utility font -******************************************************************************/ - -#define GIF_FONT_WIDTH 8 -#define GIF_FONT_HEIGHT 8 -extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH]; - -extern void GifDrawText8x8(SavedImage *Image, - const int x, const int y, - const char *legend, const int color); - -extern void GifDrawBox(SavedImage *Image, - const int x, const int y, - const int w, const int d, const int color); - -extern void GifDrawRectangle(SavedImage *Image, - const int x, const int y, - const int w, const int d, const int color); - -extern void GifDrawBoxedText8x8(SavedImage *Image, - const int x, const int y, - const char *legend, - const int border, const int bg, const int fg); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* _GIF_LIB_H */ - -/* end */ diff --git a/TMessagesProj/jni/giflib/gif_lib_private.h b/TMessagesProj/jni/giflib/gif_lib_private.h deleted file mode 100644 index adaf5571..00000000 --- a/TMessagesProj/jni/giflib/gif_lib_private.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** - -gif_lib_private.h - internal giflib routines and structures - -****************************************************************************/ - -#ifndef _GIF_LIB_PRIVATE_H -#define _GIF_LIB_PRIVATE_H - -#include "gif_lib.h" -#include "gif_hash.h" - -#define EXTENSION_INTRODUCER 0x21 -#define DESCRIPTOR_INTRODUCER 0x2c -#define TERMINATOR_INTRODUCER 0x3b - -#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ -#define LZ_BITS 12 - -#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ -#define FIRST_CODE 4097 /* Impossible code, to signal first. */ -#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ - -#define FILE_STATE_WRITE 0x01 -#define FILE_STATE_SCREEN 0x02 -#define FILE_STATE_IMAGE 0x04 -#define FILE_STATE_READ 0x08 - -#define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ) -#define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE) - -typedef struct GifFilePrivateType { - GifWord FileState, FileHandle, /* Where all this data goes to! */ - BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ - ClearCode, /* The CLEAR LZ code. */ - EOFCode, /* The EOF LZ code. */ - RunningCode, /* The next code algorithm can generate. */ - RunningBits, /* The number of bits required to represent RunningCode. */ - MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ - LastCode, /* The code before the current code. */ - CrntCode, /* Current algorithm code. */ - StackPtr, /* For character stack (see below). */ - CrntShiftState; /* Number of bits in CrntShiftDWord. */ - unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ - unsigned long PixelCount; /* Number of pixels in image. */ - FILE *File; /* File as stream. */ - InputFunc Read; /* function to read gif input (TVT) */ - OutputFunc Write; /* function to write gif output (MRB) */ - GifByteType Buf[256]; /* Compressed input is buffered here. */ - GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ - GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ - GifPrefixType Prefix[LZ_MAX_CODE + 1]; - GifHashTableType *HashTable; - bool gif89; -} GifFilePrivateType; - -#endif /* _GIF_LIB_PRIVATE_H */ - -/* end */ diff --git a/TMessagesProj/jni/giflib/gifalloc.c b/TMessagesProj/jni/giflib/gifalloc.c deleted file mode 100644 index 5726e768..00000000 --- a/TMessagesProj/jni/giflib/gifalloc.c +++ /dev/null @@ -1,400 +0,0 @@ -/***************************************************************************** - - GIF construction tools - -****************************************************************************/ - -#include -#include -#include - -#include "gif_lib.h" - -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) - -/****************************************************************************** - Miscellaneous utility functions -******************************************************************************/ - -/* return smallest bitfield size n will fit in */ -int -GifBitSize(int n) -{ - register int i; - - for (i = 1; i <= 8; i++) - if ((1 << i) >= n) - break; - return (i); -} - -/****************************************************************************** - Color map object functions -******************************************************************************/ - -/* - * Allocate a color map of given size; initialize with contents of - * ColorMap if that pointer is non-NULL. - */ -ColorMapObject * -GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) -{ - ColorMapObject *Object; - - /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to - * make the user know that or should we automatically round up instead? */ - if (ColorCount != (1 << GifBitSize(ColorCount))) { - return ((ColorMapObject *) NULL); - } - - Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); - if (Object == (ColorMapObject *) NULL) { - return ((ColorMapObject *) NULL); - } - - Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); - if (Object->Colors == (GifColorType *) NULL) { - free(Object); - return ((ColorMapObject *) NULL); - } - - Object->ColorCount = ColorCount; - Object->BitsPerPixel = GifBitSize(ColorCount); - - if (ColorMap != NULL) { - memcpy((char *)Object->Colors, - (char *)ColorMap, ColorCount * sizeof(GifColorType)); - } - - return (Object); -} - -/******************************************************************************* -Free a color map object -*******************************************************************************/ -void -GifFreeMapObject(ColorMapObject *Object) -{ - if (Object != NULL) { - (void)free(Object->Colors); - (void)free(Object); - } -} - -#ifdef DEBUG -void -DumpColorMap(ColorMapObject *Object, - FILE * fp) -{ - if (Object != NULL) { - int i, j, Len = Object->ColorCount; - - for (i = 0; i < Len; i += 4) { - for (j = 0; j < 4 && j < Len; j++) { - (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, - Object->Colors[i + j].Red, - Object->Colors[i + j].Green, - Object->Colors[i + j].Blue); - } - (void)fprintf(fp, "\n"); - } - } -} -#endif /* DEBUG */ - -/******************************************************************************* - Compute the union of two given color maps and return it. If result can't - fit into 256 colors, NULL is returned, the allocated union otherwise. - ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are - copied iff they didn't exist before. ColorTransIn2 maps the old - ColorIn2 into the ColorUnion color map table./ -*******************************************************************************/ -ColorMapObject * -GifUnionColorMap(const ColorMapObject *ColorIn1, - const ColorMapObject *ColorIn2, - GifPixelType ColorTransIn2[]) -{ - int i, j, CrntSlot, RoundUpTo, NewGifBitSize; - ColorMapObject *ColorUnion; - - /* - * We don't worry about duplicates within either color map; if - * the caller wants to resolve those, he can perform unions - * with an empty color map. - */ - - /* Allocate table which will hold the result for sure. */ - ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, - ColorIn2->ColorCount) * 2, NULL); - - if (ColorUnion == NULL) - return (NULL); - - /* - * Copy ColorIn1 to ColorUnion. - */ - for (i = 0; i < ColorIn1->ColorCount; i++) - ColorUnion->Colors[i] = ColorIn1->Colors[i]; - CrntSlot = ColorIn1->ColorCount; - - /* - * Potentially obnoxious hack: - * - * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end - * of table 1. This is very useful if your display is limited to - * 16 colors. - */ - while (ColorIn1->Colors[CrntSlot - 1].Red == 0 - && ColorIn1->Colors[CrntSlot - 1].Green == 0 - && ColorIn1->Colors[CrntSlot - 1].Blue == 0) - CrntSlot--; - - /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ - for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { - /* Let's see if this color already exists: */ - for (j = 0; j < ColorIn1->ColorCount; j++) - if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], - sizeof(GifColorType)) == 0) - break; - - if (j < ColorIn1->ColorCount) - ColorTransIn2[i] = j; /* color exists in Color1 */ - else { - /* Color is new - copy it to a new slot: */ - ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; - ColorTransIn2[i] = CrntSlot++; - } - } - - if (CrntSlot > 256) { - GifFreeMapObject(ColorUnion); - return ((ColorMapObject *) NULL); - } - - NewGifBitSize = GifBitSize(CrntSlot); - RoundUpTo = (1 << NewGifBitSize); - - if (RoundUpTo != ColorUnion->ColorCount) { - register GifColorType *Map = ColorUnion->Colors; - - /* - * Zero out slots up to next power of 2. - * We know these slots exist because of the way ColorUnion's - * start dimension was computed. - */ - for (j = CrntSlot; j < RoundUpTo; j++) - Map[j].Red = Map[j].Green = Map[j].Blue = 0; - - /* perhaps we can shrink the map? */ - if (RoundUpTo < ColorUnion->ColorCount) - ColorUnion->Colors = (GifColorType *)realloc(Map, - sizeof(GifColorType) * RoundUpTo); - } - - ColorUnion->ColorCount = RoundUpTo; - ColorUnion->BitsPerPixel = NewGifBitSize; - - return (ColorUnion); -} - -/******************************************************************************* - Apply a given color translation to the raster bits of an image -*******************************************************************************/ -void -GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) -{ - register int i; - register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; - - for (i = 0; i < RasterSize; i++) - Image->RasterBits[i] = Translation[Image->RasterBits[i]]; -} - -/****************************************************************************** - Extension record functions -******************************************************************************/ -int -GifAddExtensionBlock(int *ExtensionBlockCount, - ExtensionBlock **ExtensionBlocks, - int Function, - unsigned int Len, - unsigned char ExtData[]) -{ - ExtensionBlock *ep; - - if (*ExtensionBlocks == NULL) - *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); - else - *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks, - sizeof(ExtensionBlock) * - (*ExtensionBlockCount + 1)); - - if (*ExtensionBlocks == NULL) - return (GIF_ERROR); - - ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; - - ep->Function = Function; - ep->ByteCount=Len; - ep->Bytes = (GifByteType *)malloc(ep->ByteCount); - if (ep->Bytes == NULL) - return (GIF_ERROR); - - if (ExtData != NULL) { - memcpy(ep->Bytes, ExtData, Len); - } - - return (GIF_OK); -} - -void -GifFreeExtensions(int *ExtensionBlockCount, - ExtensionBlock **ExtensionBlocks) -{ - ExtensionBlock *ep; - - if (*ExtensionBlocks == NULL) - return; - - for (ep = *ExtensionBlocks; - ep < (*ExtensionBlocks + *ExtensionBlockCount); - ep++) - (void)free((char *)ep->Bytes); - (void)free((char *)*ExtensionBlocks); - *ExtensionBlocks = NULL; - *ExtensionBlockCount = 0; -} - -/****************************************************************************** - Image block allocation functions -******************************************************************************/ - -/* Private Function: - * Frees the last image in the GifFile->SavedImages array - */ -void -FreeLastSavedImage(GifFileType *GifFile) -{ - SavedImage *sp; - - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) - return; - - /* Remove one SavedImage from the GifFile */ - GifFile->ImageCount--; - sp = &GifFile->SavedImages[GifFile->ImageCount]; - - /* Deallocate its Colormap */ - if (sp->ImageDesc.ColorMap != NULL) { - GifFreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; - } - - /* Deallocate the image data */ - if (sp->RasterBits != NULL) - free((char *)sp->RasterBits); - - /* Deallocate any extensions */ - GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); - - /*** FIXME: We could realloc the GifFile->SavedImages structure but is - * there a point to it? Saves some memory but we'd have to do it every - * time. If this is used in GifFreeSavedImages then it would be inefficient - * (The whole array is going to be deallocated.) If we just use it when - * we want to free the last Image it's convenient to do it here. - */ -} - -/* - * Append an image block to the SavedImages array - */ -SavedImage * -GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) -{ - if (GifFile->SavedImages == NULL) - GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); - else - GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, - sizeof(SavedImage) * (GifFile->ImageCount + 1)); - - if (GifFile->SavedImages == NULL) - return ((SavedImage *)NULL); - else { - SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; - memset((char *)sp, '\0', sizeof(SavedImage)); - - if (CopyFrom != NULL) { - memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); - - /* - * Make our own allocated copies of the heap fields in the - * copied record. This guards against potential aliasing - * problems. - */ - - /* first, the local color map */ - if (sp->ImageDesc.ColorMap != NULL) { - sp->ImageDesc.ColorMap = GifMakeMapObject( - CopyFrom->ImageDesc.ColorMap->ColorCount, - CopyFrom->ImageDesc.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - } - - /* next, the raster */ - sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * - CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width); - if (sp->RasterBits == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - memcpy(sp->RasterBits, CopyFrom->RasterBits, - sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width); - - /* finally, the extension blocks */ - if (sp->ExtensionBlocks != NULL) { - sp->ExtensionBlocks = (ExtensionBlock *)malloc( - sizeof(ExtensionBlock) * - CopyFrom->ExtensionBlockCount); - if (sp->ExtensionBlocks == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, - sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); - } - } - - return (sp); - } -} - -void -GifFreeSavedImages(GifFileType *GifFile) -{ - SavedImage *sp; - - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { - return; - } - for (sp = GifFile->SavedImages; - sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { - if (sp->ImageDesc.ColorMap != NULL) { - GifFreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; - } - - if (sp->RasterBits != NULL) - free((char *)sp->RasterBits); - - GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); - } - free((char *)GifFile->SavedImages); - GifFile->SavedImages = NULL; -} - -/* end */ diff --git a/TMessagesProj/jni/image.c b/TMessagesProj/jni/image.c index 5445075b..f7a2cfef 100644 --- a/TMessagesProj/jni/image.c +++ b/TMessagesProj/jni/image.c @@ -68,7 +68,7 @@ static void fastBlurMore(int imageWidth, int imageHeight, int imageStride, void const int r1 = radius + 1; const int div = radius * 2 + 1; - if (radius > 15 || div >= w || div >= h || w * h > 128 * 128 || imageStride > imageWidth * 4) { + if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || imageStride > imageWidth * 4) { return; } @@ -151,6 +151,9 @@ static void fastBlurMore(int imageWidth, int imageHeight, int imageStride, void static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pixels, int radius) { uint8_t *pix = (uint8_t *)pixels; + if (pix == NULL) { + return; + } const int w = imageWidth; const int h = imageHeight; const int stride = imageStride; @@ -169,7 +172,7 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix return; } - if (radius > 15 || div >= w || div >= h || w * h > 128 * 128 || imageStride > imageWidth * 4) { + if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || imageStride > imageWidth * 4) { return; } @@ -265,18 +268,12 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) { longjmp(myerr->setjmp_buffer, 1); } -JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius, int unpin) { +JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius, int unpin, int width, int height, int stride) { if (!bitmap) { return; } - AndroidBitmapInfo info; - - if (AndroidBitmap_getInfo(env, bitmap, &info) < 0) { - return; - } - - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888 || !info.width || !info.height || !info.stride) { + if (!width || !height || !stride) { return; } @@ -285,9 +282,9 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl return; } if (radius <= 3) { - fastBlur(info.width, info.height, info.stride, pixels, radius); + fastBlur(width, height, stride, pixels, radius); } else { - fastBlurMore(info.width, info.height, info.stride, pixels, radius); + fastBlurMore(width, height, stride, pixels, radius); } if (unpin) { AndroidBitmap_unlockPixels(env, bitmap); @@ -399,10 +396,20 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass } JNIEXPORT int Java_org_telegram_messenger_Utilities_pinBitmap(JNIEnv *env, jclass class, jobject bitmap) { + if (bitmap == NULL) { + return; + } unsigned char *pixels; return AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 ? 1 : 0; } +JNIEXPORT int Java_org_telegram_messenger_Utilities_unpinBitmap(JNIEnv *env, jclass class, jobject bitmap) { + if (bitmap == NULL) { + return; + } + AndroidBitmap_unlockPixels(env, bitmap); +} + JNIEXPORT void Java_org_telegram_messenger_Utilities_loadBitmap(JNIEnv *env, jclass class, jstring path, jobject bitmap, int scale, int width, int height, int stride) { AndroidBitmapInfo info; diff --git a/TMessagesProj/jni/jni.c b/TMessagesProj/jni/jni.c index 2bf21689..f300f8e7 100644 --- a/TMessagesProj/jni/jni.c +++ b/TMessagesProj/jni/jni.c @@ -7,10 +7,10 @@ #include #include "utils.h" #include "sqlite.h" -#include "gif.h" #include "image.h" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env); +int gifvideoOnJNILoad(JavaVM *vm, JNIEnv *env); jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = 0; @@ -27,18 +27,20 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { if (imageOnJNILoad(vm, reserved, env) == -1) { return -1; } + + if (gifvideoOnJNILoad(vm, env) == -1) { + return -1; + } if (registerNativeTgNetFunctions(vm, env) != JNI_TRUE) { return -1; } - gifOnJNILoad(vm, reserved, env); - return JNI_VERSION_1_6; } void JNI_OnUnload(JavaVM *vm, void *reserved) { - gifOnJNIUnload(vm, reserved); + } JNIEXPORT void Java_org_telegram_messenger_Utilities_aesIgeEncryption(JNIEnv *env, jclass class, jobject buffer, jbyteArray key, jbyteArray iv, jboolean encrypt, int offset, int length) { diff --git a/TMessagesProj/jni/libyuv/include/libyuv.h b/TMessagesProj/jni/libyuv/include/libyuv.h index 3bebe642..de652836 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv.h +++ b/TMessagesProj/jni/libyuv/include/libyuv.h @@ -18,7 +18,6 @@ #include "libyuv/convert_from.h" #include "libyuv/convert_from_argb.h" #include "libyuv/cpu_id.h" -#include "libyuv/format_conversion.h" #include "libyuv/mjpeg_decoder.h" #include "libyuv/planar_functions.h" #include "libyuv/rotate.h" diff --git a/TMessagesProj/jni/libyuv/include/libyuv/compare.h b/TMessagesProj/jni/libyuv/include/libyuv/compare.h index 5dfac7c8..08b2bb2e 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/compare.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/compare.h @@ -22,6 +22,11 @@ extern "C" { LIBYUV_API uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed); +// Scan an opaque argb image and return fourcc based on alpha offset. +// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. +LIBYUV_API +uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height); + // Sum Square Error - used to compute Mean Square Error or PSNR. LIBYUV_API uint64 ComputeSumSquareError(const uint8* src_a, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/convert.h b/TMessagesProj/jni/libyuv/include/libyuv/convert.h index 1bd45c83..a8d3fa07 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/convert.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/convert.h @@ -71,6 +71,8 @@ int I400ToI420(const uint8* src_y, int src_stride_y, uint8* dst_v, int dst_stride_v, int width, int height); +#define J400ToJ420 I400ToI420 + // Convert NV12 to I420. LIBYUV_API int NV12ToI420(const uint8* src_y, int src_stride_y, @@ -113,15 +115,6 @@ int M420ToI420(const uint8* src_m420, int src_stride_m420, uint8* dst_v, int dst_stride_v, int width, int height); -// Convert Q420 to I420. -LIBYUV_API -int Q420ToI420(const uint8* src_y, int src_stride_y, - const uint8* src_yuy2, int src_stride_yuy2, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height); - // ARGB little endian (bgra in memory) to I420. LIBYUV_API int ARGBToI420(const uint8* src_frame, int src_stride_frame, @@ -211,8 +204,6 @@ int MJPGSize(const uint8* sample, size_t sample_size, int* width, int* height); #endif -// Note Bayer formats (BGGR) To I420 are in format_conversion.h - // Convert camera sample to I420 with cropping, rotation and vertical flip. // "src_size" is needed to parse MJPG. // "dst_stride_y" number of bytes in a row of the dst_y plane. diff --git a/TMessagesProj/jni/libyuv/include/libyuv/convert_argb.h b/TMessagesProj/jni/libyuv/include/libyuv/convert_argb.h index a18014ca..ce4e3d07 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/convert_argb.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/convert_argb.h @@ -18,7 +18,6 @@ #include "libyuv/rotate.h" // TODO(fbarchard): This set of functions should exactly match convert.h -// Add missing Q420. // TODO(fbarchard): Add tests. Create random content of right size and convert // with C vs Opt and or to I420 and compare. // TODO(fbarchard): Some of these functions lack parameter setting. @@ -61,6 +60,22 @@ int I444ToARGB(const uint8* src_y, int src_stride_y, uint8* dst_argb, int dst_stride_argb, int width, int height); +// Convert J444 to ARGB. +LIBYUV_API +int J444ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert I444 to ABGR. +LIBYUV_API +int I444ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height); + // Convert I411 to ARGB. LIBYUV_API int I411ToARGB(const uint8* src_y, int src_stride_y, @@ -69,20 +84,38 @@ int I411ToARGB(const uint8* src_y, int src_stride_y, uint8* dst_argb, int dst_stride_argb, int width, int height); -// Convert I400 (grey) to ARGB. +// Convert I420 with Alpha to preattenuated ARGB. +LIBYUV_API +int I420AlphaToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + const uint8* src_a, int src_stride_a, + uint8* dst_argb, int dst_stride_argb, + int width, int height, int attenuate); + +// Convert I420 with Alpha to preattenuated ABGR. +LIBYUV_API +int I420AlphaToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + const uint8* src_a, int src_stride_a, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height, int attenuate); + +// Convert I400 (grey) to ARGB. Reverse of ARGBToI400. LIBYUV_API int I400ToARGB(const uint8* src_y, int src_stride_y, uint8* dst_argb, int dst_stride_argb, int width, int height); -// Alias. -#define YToARGB I400ToARGB_Reference - -// Convert I400 to ARGB. Reverse of ARGBToI400. +// Convert J400 (jpeg grey) to ARGB. LIBYUV_API -int I400ToARGB_Reference(const uint8* src_y, int src_stride_y, - uint8* dst_argb, int dst_stride_argb, - int width, int height); +int J400ToARGB(const uint8* src_y, int src_stride_y, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Alias. +#define YToARGB I400ToARGB // Convert NV12 to ARGB. LIBYUV_API @@ -104,13 +137,6 @@ int M420ToARGB(const uint8* src_m420, int src_stride_m420, uint8* dst_argb, int dst_stride_argb, int width, int height); -// TODO(fbarchard): Convert Q420 to ARGB. -// LIBYUV_API -// int Q420ToARGB(const uint8* src_y, int src_stride_y, -// const uint8* src_yuy2, int src_stride_yuy2, -// uint8* dst_argb, int dst_stride_argb, -// int width, int height); - // Convert YUY2 to ARGB. LIBYUV_API int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, @@ -123,6 +149,70 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_argb, int dst_stride_argb, int width, int height); +// Convert J420 to ARGB. +LIBYUV_API +int J420ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert J422 to ARGB. +LIBYUV_API +int J422ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert J420 to ABGR. +LIBYUV_API +int J420ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height); + +// Convert J422 to ABGR. +LIBYUV_API +int J422ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height); + +// Convert H420 to ARGB. +LIBYUV_API +int H420ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert H422 to ARGB. +LIBYUV_API +int H422ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert H420 to ABGR. +LIBYUV_API +int H420ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height); + +// Convert H422 to ABGR. +LIBYUV_API +int H422ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height); + // BGRA little endian (argb in memory) to ARGB. LIBYUV_API int BGRAToARGB(const uint8* src_frame, int src_stride_frame, @@ -184,8 +274,6 @@ int MJPGToARGB(const uint8* sample, size_t sample_size, int dst_width, int dst_height); #endif -// Note Bayer formats (BGGR) to ARGB are in format_conversion.h. - // Convert camera sample to ARGB with cropping, rotation and vertical flip. // "src_size" is needed to parse MJPG. // "dst_stride_argb" number of bytes in a row of the dst_argb plane. diff --git a/TMessagesProj/jni/libyuv/include/libyuv/convert_from.h b/TMessagesProj/jni/libyuv/include/libyuv/convert_from.h index b1cf57f7..9fd8d4de 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/convert_from.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/convert_from.h @@ -57,7 +57,6 @@ int I400Copy(const uint8* src_y, int src_stride_y, int width, int height); // TODO(fbarchard): I420ToM420 -// TODO(fbarchard): I420ToQ420 LIBYUV_API int I420ToNV12(const uint8* src_y, int src_stride_y, @@ -138,6 +137,17 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, uint8* dst_frame, int dst_stride_frame, int width, int height); +// Convert I420 To RGB565 with 4x4 dither matrix (16 bytes). +// Values in dither matrix from 0 to 7 recommended. +// The order of the dither matrix is first byte is upper left. + +LIBYUV_API +int I420ToRGB565Dither(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_frame, int dst_stride_frame, + const uint8* dither4x4, int width, int height); + LIBYUV_API int I420ToARGB1555(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, @@ -152,8 +162,6 @@ int I420ToARGB4444(const uint8* src_y, int src_stride_y, uint8* dst_frame, int dst_stride_frame, int width, int height); -// Note Bayer formats (BGGR) To I420 are in format_conversion.h. - // Convert I420 to specified format. // "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the // buffer has contiguous rows. Can be negative. A multiple of 16 is optimal. diff --git a/TMessagesProj/jni/libyuv/include/libyuv/convert_from_argb.h b/TMessagesProj/jni/libyuv/include/libyuv/convert_from_argb.h index 90f43af0..1df53200 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/convert_from_argb.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/convert_from_argb.h @@ -61,6 +61,16 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, uint8* dst_rgb565, int dst_stride_rgb565, int width, int height); +// Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). +// Values in dither matrix from 0 to 7 recommended. +// The order of the dither matrix is first byte is upper left. +// TODO(fbarchard): Consider pointer to 2d array for dither4x4. +// const uint8(*dither)[4][4]; +LIBYUV_API +int ARGBToRGB565Dither(const uint8* src_argb, int src_stride_argb, + uint8* dst_rgb565, int dst_stride_rgb565, + const uint8* dither4x4, int width, int height); + // Convert ARGB To ARGB1555. LIBYUV_API int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, @@ -105,6 +115,14 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, uint8* dst_v, int dst_stride_v, int width, int height); +// Convert ARGB to J422. +LIBYUV_API +int ARGBToJ422(const uint8* src_argb, int src_stride_argb, + uint8* dst_yj, int dst_stride_yj, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height); + // Convert ARGB To I411. LIBYUV_API int ARGBToI411(const uint8* src_argb, int src_stride_argb, @@ -125,6 +143,12 @@ int ARGBToI400(const uint8* src_argb, int src_stride_argb, uint8* dst_y, int dst_stride_y, int width, int height); +// Convert ARGB to G. (Reverse of J400toARGB, which replicates G back to ARGB) +LIBYUV_API +int ARGBToG(const uint8* src_argb, int src_stride_argb, + uint8* dst_g, int dst_stride_g, + int width, int height); + // Convert ARGB To NV12. LIBYUV_API int ARGBToNV12(const uint8* src_argb, int src_stride_argb, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/cpu_id.h b/TMessagesProj/jni/libyuv/include/libyuv/cpu_id.h index dc858a81..a83edd50 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/cpu_id.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/cpu_id.h @@ -18,9 +18,8 @@ namespace libyuv { extern "C" { #endif -// TODO(fbarchard): Consider overlapping bits for different architectures. // Internal flag to indicate cpuid requires initialization. -#define kCpuInit 0x1 +static const int kCpuInitialized = 0x1; // These flags are only valid on ARM processors. static const int kCpuHasARM = 0x2; @@ -37,12 +36,12 @@ static const int kCpuHasAVX = 0x200; static const int kCpuHasAVX2 = 0x400; static const int kCpuHasERMS = 0x800; static const int kCpuHasFMA3 = 0x1000; +static const int kCpuHasAVX3 = 0x2000; // 0x2000, 0x4000, 0x8000 reserved for future X86 flags. // These flags are only valid on MIPS processors. static const int kCpuHasMIPS = 0x10000; -static const int kCpuHasMIPS_DSP = 0x20000; -static const int kCpuHasMIPS_DSPR2 = 0x40000; +static const int kCpuHasMIPS_DSPR2 = 0x20000; // Internal function used to auto-init. LIBYUV_API @@ -57,7 +56,7 @@ int ArmCpuCaps(const char* cpuinfo_name); // returns non-zero if instruction set is detected static __inline int TestCpuFlag(int test_flag) { LIBYUV_API extern int cpu_info_; - return (cpu_info_ == kCpuInit ? InitCpuFlags() : cpu_info_) & test_flag; + return (!cpu_info_ ? InitCpuFlags() : cpu_info_) & test_flag; } // For testing, allow CPU flags to be disabled. diff --git a/TMessagesProj/jni/libyuv/include/libyuv/format_conversion.h b/TMessagesProj/jni/libyuv/include/libyuv/format_conversion.h deleted file mode 100644 index b18bf053..00000000 --- a/TMessagesProj/jni/libyuv/include/libyuv/format_conversion.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2011 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef INCLUDE_LIBYUV_FORMATCONVERSION_H_ // NOLINT -#define INCLUDE_LIBYUV_FORMATCONVERSION_H_ - -#include "libyuv/basic_types.h" - -#ifdef __cplusplus -namespace libyuv { -extern "C" { -#endif - -// Convert Bayer RGB formats to I420. -LIBYUV_API -int BayerBGGRToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height); - -LIBYUV_API -int BayerGBRGToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height); - -LIBYUV_API -int BayerGRBGToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height); - -LIBYUV_API -int BayerRGGBToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height); - -// Temporary API mapper. -#define BayerRGBToI420(b, bs, f, y, ys, u, us, v, vs, w, h) \ - BayerToI420(b, bs, y, ys, u, us, v, vs, w, h, f) - -LIBYUV_API -int BayerToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height, - uint32 src_fourcc_bayer); - -// Convert I420 to Bayer RGB formats. -LIBYUV_API -int I420ToBayerBGGR(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_frame, int dst_stride_frame, - int width, int height); - -LIBYUV_API -int I420ToBayerGBRG(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_frame, int dst_stride_frame, - int width, int height); - -LIBYUV_API -int I420ToBayerGRBG(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_frame, int dst_stride_frame, - int width, int height); - -LIBYUV_API -int I420ToBayerRGGB(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_frame, int dst_stride_frame, - int width, int height); - -// Temporary API mapper. -#define I420ToBayerRGB(y, ys, u, us, v, vs, b, bs, f, w, h) \ - I420ToBayer(y, ys, u, us, v, vs, b, bs, w, h, f) - -LIBYUV_API -int I420ToBayer(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_frame, int dst_stride_frame, - int width, int height, - uint32 dst_fourcc_bayer); - -// Convert Bayer RGB formats to ARGB. -LIBYUV_API -int BayerBGGRToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height); - -LIBYUV_API -int BayerGBRGToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height); - -LIBYUV_API -int BayerGRBGToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height); - -LIBYUV_API -int BayerRGGBToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height); - -// Temporary API mapper. -#define BayerRGBToARGB(b, bs, f, a, as, w, h) BayerToARGB(b, bs, a, as, w, h, f) - -LIBYUV_API -int BayerToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height, - uint32 src_fourcc_bayer); - -// Converts ARGB to Bayer RGB formats. -LIBYUV_API -int ARGBToBayerBGGR(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height); - -LIBYUV_API -int ARGBToBayerGBRG(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height); - -LIBYUV_API -int ARGBToBayerGRBG(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height); - -LIBYUV_API -int ARGBToBayerRGGB(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height); - -// Temporary API mapper. -#define ARGBToBayerRGB(a, as, b, bs, f, w, h) ARGBToBayer(b, bs, a, as, w, h, f) - -LIBYUV_API -int ARGBToBayer(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height, - uint32 dst_fourcc_bayer); - -#ifdef __cplusplus -} // extern "C" -} // namespace libyuv -#endif - -#endif // INCLUDE_LIBYUV_FORMATCONVERSION_H_ NOLINT diff --git a/TMessagesProj/jni/libyuv/include/libyuv/planar_functions.h b/TMessagesProj/jni/libyuv/include/libyuv/planar_functions.h index d10a1698..9d30225d 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/planar_functions.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/planar_functions.h @@ -45,6 +45,7 @@ int I400ToI400(const uint8* src_y, int src_stride_y, uint8* dst_y, int dst_stride_y, int width, int height); +#define J400ToJ400 I400ToI400 // Copy I422 to I422. #define I422ToI422 I422Copy @@ -84,6 +85,18 @@ int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_v, int dst_stride_v, int width, int height); +LIBYUV_API +int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2, + uint8* dst_y, int dst_stride_y, + uint8* dst_uv, int dst_stride_uv, + int width, int height); + +LIBYUV_API +int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, + uint8* dst_y, int dst_stride_y, + uint8* dst_uv, int dst_stride_uv, + int width, int height); + // Convert I420 to I400. (calls CopyPlane ignoring u/v). LIBYUV_API int I420ToI400(const uint8* src_y, int src_stride_y, @@ -93,6 +106,7 @@ int I420ToI400(const uint8* src_y, int src_stride_y, int width, int height); // Alias +#define J420ToJ400 I420ToI400 #define I420ToI420Mirror I420Mirror // I420 mirror. @@ -131,13 +145,6 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y, uint8* dst_rgb565, int dst_stride_rgb565, int width, int height); -// Convert NV21 to RGB565. -LIBYUV_API -int NV21ToRGB565(const uint8* src_y, int src_stride_y, - const uint8* src_uv, int src_stride_uv, - uint8* dst_rgb565, int dst_stride_rgb565, - int width, int height); - // I422ToARGB is in convert_argb.h // Convert I422 to BGRA. LIBYUV_API @@ -163,6 +170,14 @@ int I422ToRGBA(const uint8* src_y, int src_stride_y, uint8* dst_rgba, int dst_stride_rgba, int width, int height); +// Alias +#define RGB24ToRAW RAWToRGB24 + +LIBYUV_API +int RAWToRGB24(const uint8* src_raw, int src_stride_raw, + uint8* dst_rgb24, int dst_stride_rgb24, + int width, int height); + // Draw a rectangle into I420. LIBYUV_API int I420Rect(uint8* dst_y, int dst_stride_y, @@ -267,13 +282,13 @@ int ARGBCopy(const uint8* src_argb, int src_stride_argb, uint8* dst_argb, int dst_stride_argb, int width, int height); -// Copy ARGB to ARGB. +// Copy Alpha channel of ARGB to alpha of ARGB. LIBYUV_API int ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb, uint8* dst_argb, int dst_stride_argb, int width, int height); -// Copy ARGB to ARGB. +// Copy Y channel to Alpha of ARGB. LIBYUV_API int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, uint8* dst_argb, int dst_stride_argb, @@ -287,6 +302,7 @@ LIBYUV_API ARGBBlendRow GetARGBBlend(); // Alpha Blend ARGB images and store to destination. +// Source is pre-multiplied by alpha using ARGBAttenuate. // Alpha of destination is set to 255. LIBYUV_API int ARGBBlend(const uint8* src_argb0, int src_stride_argb0, @@ -294,6 +310,31 @@ int ARGBBlend(const uint8* src_argb0, int src_stride_argb0, uint8* dst_argb, int dst_stride_argb, int width, int height); +// Alpha Blend plane and store to destination. +// Source is not pre-multiplied by alpha. +LIBYUV_API +int BlendPlane(const uint8* src_y0, int src_stride_y0, + const uint8* src_y1, int src_stride_y1, + const uint8* alpha, int alpha_stride, + uint8* dst_y, int dst_stride_y, + int width, int height); + +// Alpha Blend YUV images and store to destination. +// Source is not pre-multiplied by alpha. +// Alpha is full width x height and subsampled to half size to apply to UV. +LIBYUV_API +int I420Blend(const uint8* src_y0, int src_stride_y0, + const uint8* src_u0, int src_stride_u0, + const uint8* src_v0, int src_stride_v0, + const uint8* src_y1, int src_stride_y1, + const uint8* src_u1, int src_stride_u1, + const uint8* src_v1, int src_stride_v1, + const uint8* alpha, int alpha_stride, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height); + // Multiply ARGB image by ARGB image. Shifted down by 8. Saturates to 255. LIBYUV_API int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, @@ -375,36 +416,57 @@ int ARGBShade(const uint8* src_argb, int src_stride_argb, uint8* dst_argb, int dst_stride_argb, int width, int height, uint32 value); -// Interpolate between two ARGB images using specified amount of interpolation +// Interpolate between two images using specified amount of interpolation // (0 to 255) and store to destination. -// 'interpolation' is specified as 8 bit fraction where 0 means 100% src_argb0 -// and 255 means 1% src_argb0 and 99% src_argb1. -// Internally uses ARGBScale bilinear filtering. -// Caveat: This function will write up to 16 bytes beyond the end of dst_argb. +// 'interpolation' is specified as 8 bit fraction where 0 means 100% src0 +// and 255 means 1% src0 and 99% src1. +LIBYUV_API +int InterpolatePlane(const uint8* src0, int src_stride0, + const uint8* src1, int src_stride1, + uint8* dst, int dst_stride, + int width, int height, int interpolation); + +// Interpolate between two ARGB images using specified amount of interpolation +// Internally calls InterpolatePlane with width * 4 (bpp). LIBYUV_API int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0, const uint8* src_argb1, int src_stride_argb1, uint8* dst_argb, int dst_stride_argb, int width, int height, int interpolation); -#if defined(__pnacl__) || defined(__CLR_VER) || defined(COVERAGE_ENABLED) || \ - defined(TARGET_IPHONE_SIMULATOR) +// Interpolate between two YUV images using specified amount of interpolation +// Internally calls InterpolatePlane on each plane where the U and V planes +// are half width and half height. +LIBYUV_API +int I420Interpolate(const uint8* src0_y, int src0_stride_y, + const uint8* src0_u, int src0_stride_u, + const uint8* src0_v, int src0_stride_v, + const uint8* src1_y, int src1_stride_y, + const uint8* src1_u, int src1_stride_u, + const uint8* src1_v, int src1_stride_v, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height, int interpolation); + +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__i386__) && !defined(__SSE2__)) #define LIBYUV_DISABLE_X86 #endif +// The following are available on all x86 platforms: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) +#define HAS_ARGBAFFINEROW_SSE2 +#endif -// Row functions for copying a pixels from a source with a slope to a row +// Row function for copying pixels from a source with a slope to a row // of destination. Useful for scaling, rotation, mirror, texture mapping. LIBYUV_API void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride, uint8* dst_argb, const float* uv_dudv, int width); -// The following are available on all x86 platforms: -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) LIBYUV_API void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, uint8* dst_argb, const float* uv_dudv, int width); -#define HAS_ARGBAFFINEROW_SSE2 -#endif // LIBYUV_DISABLE_X86 // Shuffle ARGB channel order. e.g. BGRA to ARGB. // shuffler is 16 bytes and must be aligned. diff --git a/TMessagesProj/jni/libyuv/include/libyuv/row.h b/TMessagesProj/jni/libyuv/include/libyuv/row.h index 477b2744..f7620eea 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/row.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/row.h @@ -15,10 +15,6 @@ #include "libyuv/basic_types.h" -#if defined(__native_client__) -#include "ppapi/c/pp_macros.h" // For PPAPI_RELEASE -#endif - #ifdef __cplusplus namespace libyuv { extern "C" { @@ -41,9 +37,8 @@ extern "C" { free(var##_mem); \ var = 0 -#if defined(__pnacl__) || defined(__CLR_VER) || defined(COVERAGE_ENABLED) || \ - defined(TARGET_IPHONE_SIMULATOR) || \ - (defined(_MSC_VER) && defined(__clang__)) +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__i386__) && !defined(__SSE2__)) #define LIBYUV_DISABLE_X86 #endif // True if compiling for SSSE3 as a requirement. @@ -51,121 +46,15 @@ extern "C" { #define LIBYUV_SSSE3_ONLY #endif -// Enable for NaCL pepper 33 for bundle and AVX2 support. -#if defined(__native_client__) && PPAPI_RELEASE >= 33 -#define NEW_BINUTILS -#endif -#if defined(__native_client__) && defined(__arm__) && PPAPI_RELEASE < 37 +#if defined(__native_client__) #define LIBYUV_DISABLE_NEON #endif - -// The following are available on all x86 platforms: -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -// Effects: -#define HAS_ARGBADDROW_SSE2 -#define HAS_ARGBAFFINEROW_SSE2 -#define HAS_ARGBATTENUATEROW_SSSE3 -#define HAS_ARGBBLENDROW_SSSE3 -#define HAS_ARGBCOLORMATRIXROW_SSSE3 -#define HAS_ARGBCOLORTABLEROW_X86 -#define HAS_ARGBCOPYALPHAROW_SSE2 -#define HAS_ARGBCOPYYTOALPHAROW_SSE2 -#define HAS_ARGBGRAYROW_SSSE3 -#define HAS_ARGBLUMACOLORTABLEROW_SSSE3 -#define HAS_ARGBMIRRORROW_SSSE3 -#define HAS_ARGBMULTIPLYROW_SSE2 -#define HAS_ARGBPOLYNOMIALROW_SSE2 -#define HAS_ARGBQUANTIZEROW_SSE2 -#define HAS_ARGBSEPIAROW_SSSE3 -#define HAS_ARGBSHADEROW_SSE2 -#define HAS_ARGBSUBTRACTROW_SSE2 -#define HAS_ARGBTOUVROW_SSSE3 -#define HAS_ARGBUNATTENUATEROW_SSE2 -#define HAS_COMPUTECUMULATIVESUMROW_SSE2 -#define HAS_CUMULATIVESUMTOAVERAGEROW_SSE2 -#define HAS_INTERPOLATEROW_SSE2 -#define HAS_INTERPOLATEROW_SSSE3 -#define HAS_RGBCOLORTABLEROW_X86 -#define HAS_SOBELROW_SSE2 -#define HAS_SOBELTOPLANEROW_SSE2 -#define HAS_SOBELXROW_SSE2 -#define HAS_SOBELXYROW_SSE2 -#define HAS_SOBELYROW_SSE2 - -// Conversions: -#define HAS_ABGRTOUVROW_SSSE3 -#define HAS_ABGRTOYROW_SSSE3 -#define HAS_ARGB1555TOARGBROW_SSE2 -#define HAS_ARGB4444TOARGBROW_SSE2 -#define HAS_ARGBSHUFFLEROW_SSE2 -#define HAS_ARGBSHUFFLEROW_SSSE3 -#define HAS_ARGBTOARGB1555ROW_SSE2 -#define HAS_ARGBTOARGB4444ROW_SSE2 -#define HAS_ARGBTOBAYERGGROW_SSE2 -#define HAS_ARGBTOBAYERROW_SSSE3 -#define HAS_ARGBTORAWROW_SSSE3 -#define HAS_ARGBTORGB24ROW_SSSE3 -#define HAS_ARGBTORGB565ROW_SSE2 -#define HAS_ARGBTOUV422ROW_SSSE3 -#define HAS_ARGBTOUV444ROW_SSSE3 -#define HAS_ARGBTOUVJROW_SSSE3 -#define HAS_ARGBTOYJROW_SSSE3 -#define HAS_ARGBTOYROW_SSSE3 -#define HAS_BGRATOUVROW_SSSE3 -#define HAS_BGRATOYROW_SSSE3 -#define HAS_COPYROW_ERMS -#define HAS_COPYROW_SSE2 -#define HAS_COPYROW_X86 -#define HAS_HALFROW_SSE2 -#define HAS_I400TOARGBROW_SSE2 -#define HAS_I411TOARGBROW_SSSE3 -#define HAS_I422TOARGB1555ROW_SSSE3 -#define HAS_I422TOABGRROW_SSSE3 -#define HAS_I422TOARGB1555ROW_SSSE3 -#define HAS_I422TOARGB4444ROW_SSSE3 -#define HAS_I422TOARGBROW_SSSE3 -#define HAS_I422TOBGRAROW_SSSE3 -#define HAS_I422TORAWROW_SSSE3 -#define HAS_I422TORGB24ROW_SSSE3 -#define HAS_I422TORGB565ROW_SSSE3 -#define HAS_I422TORGBAROW_SSSE3 -#define HAS_I422TOUYVYROW_SSE2 -#define HAS_I422TOYUY2ROW_SSE2 -#define HAS_I444TOARGBROW_SSSE3 -#define HAS_MERGEUVROW_SSE2 -#define HAS_MIRRORROW_SSE2 -#define HAS_MIRRORROW_SSSE3 -#define HAS_MIRRORROW_UV_SSSE3 -#define HAS_MIRRORUVROW_SSSE3 -#define HAS_NV12TOARGBROW_SSSE3 -#define HAS_NV12TORGB565ROW_SSSE3 -#define HAS_NV21TOARGBROW_SSSE3 -#define HAS_NV21TORGB565ROW_SSSE3 -#define HAS_RAWTOARGBROW_SSSE3 -#define HAS_RAWTOYROW_SSSE3 -#define HAS_RGB24TOARGBROW_SSSE3 -#define HAS_RGB24TOYROW_SSSE3 -#define HAS_RGB565TOARGBROW_SSE2 -#define HAS_RGBATOUVROW_SSSE3 -#define HAS_RGBATOYROW_SSSE3 -#define HAS_SETROW_X86 -#define HAS_SPLITUVROW_SSE2 -#define HAS_UYVYTOARGBROW_SSSE3 -#define HAS_UYVYTOUV422ROW_SSE2 -#define HAS_UYVYTOUVROW_SSE2 -#define HAS_UYVYTOYROW_SSE2 -#define HAS_YTOARGBROW_SSE2 -#define HAS_YUY2TOARGBROW_SSSE3 -#define HAS_YUY2TOUV422ROW_SSE2 -#define HAS_YUY2TOUVROW_SSE2 -#define HAS_YUY2TOYROW_SSE2 -#endif - -// The following are available on x64 Visual C: -#if !defined(LIBYUV_DISABLE_X86) && defined (_M_X64) -#define HAS_I422TOARGBROW_SSSE3 -#endif +// clang >= 3.5.0 required for Arm64. +#if defined(__clang__) && defined(__aarch64__) && !defined(LIBYUV_DISABLE_NEON) +#if (__clang_major__ < 3) || (__clang_major__ == 3 && (__clang_minor__ < 5)) +#define LIBYUV_DISABLE_NEON +#endif // clang >= 3.5 +#endif // __clang__ // GCC >= 4.7.0 required for AVX2. #if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) @@ -182,37 +71,158 @@ extern "C" { #endif // __clang__ // Visual C 2012 required for AVX2. -#if defined(_M_IX86) && defined(_MSC_VER) && _MSC_VER >= 1700 +#if defined(_M_IX86) && !defined(__clang__) && \ + defined(_MSC_VER) && _MSC_VER >= 1700 #define VISUALC_HAS_AVX2 1 #endif // VisualStudio >= 2012 +// The following are available on all x86 platforms: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) +// Conversions: +#define HAS_ABGRTOUVROW_SSSE3 +#define HAS_ABGRTOYROW_SSSE3 +#define HAS_ARGB1555TOARGBROW_SSE2 +#define HAS_ARGB4444TOARGBROW_SSE2 +#define HAS_ARGBSETROW_X86 +#define HAS_ARGBSHUFFLEROW_SSE2 +#define HAS_ARGBSHUFFLEROW_SSSE3 +#define HAS_ARGBTOARGB1555ROW_SSE2 +#define HAS_ARGBTOARGB4444ROW_SSE2 +#define HAS_ARGBTORAWROW_SSSE3 +#define HAS_ARGBTORGB24ROW_SSSE3 +#define HAS_ARGBTORGB565DITHERROW_SSE2 +#define HAS_ARGBTORGB565ROW_SSE2 +#define HAS_ARGBTOUV422ROW_SSSE3 +#define HAS_ARGBTOUV444ROW_SSSE3 +#define HAS_ARGBTOUVJROW_SSSE3 +#define HAS_ARGBTOUVROW_SSSE3 +#define HAS_ARGBTOYJROW_SSSE3 +#define HAS_ARGBTOYROW_SSSE3 +#define HAS_BGRATOUVROW_SSSE3 +#define HAS_BGRATOYROW_SSSE3 +#define HAS_COPYROW_ERMS +#define HAS_COPYROW_SSE2 +#define HAS_H422TOARGBROW_SSSE3 +#define HAS_I400TOARGBROW_SSE2 +// The following functions fail on gcc/clang 32 bit with fpic and framepointer. +// caveat: clangcl uses row_win.cc which works. +#if defined(NDEBUG) || !(defined(_DEBUG) && defined(__i386__)) || \ + !defined(__i386__) || defined(_MSC_VER) +// TODO(fbarchard): fix build error on x86 debug +// https://code.google.com/p/libyuv/issues/detail?id=524 +#define HAS_I411TOARGBROW_SSSE3 +// TODO(fbarchard): fix build error on android_full_debug=1 +// https://code.google.com/p/libyuv/issues/detail?id=517 +#define HAS_I422ALPHATOARGBROW_SSSE3 +#endif +#define HAS_I422TOARGB1555ROW_SSSE3 +#define HAS_I422TOARGB4444ROW_SSSE3 +#define HAS_I422TOARGBROW_SSSE3 +#define HAS_I422TORGB24ROW_SSSE3 +#define HAS_I422TORGB565ROW_SSSE3 +#define HAS_I422TORGBAROW_SSSE3 +#define HAS_I422TOUYVYROW_SSE2 +#define HAS_I422TOYUY2ROW_SSE2 +#define HAS_I444TOARGBROW_SSSE3 +#define HAS_J400TOARGBROW_SSE2 +#define HAS_J422TOARGBROW_SSSE3 +#define HAS_MERGEUVROW_SSE2 +#define HAS_MIRRORROW_SSSE3 +#define HAS_MIRRORROW_UV_SSSE3 +#define HAS_MIRRORUVROW_SSSE3 +#define HAS_NV12TOARGBROW_SSSE3 +#define HAS_NV12TORGB565ROW_SSSE3 +#define HAS_NV21TOARGBROW_SSSE3 +#define HAS_RAWTOARGBROW_SSSE3 +#define HAS_RAWTORGB24ROW_SSSE3 +#define HAS_RAWTOYROW_SSSE3 +#define HAS_RGB24TOARGBROW_SSSE3 +#define HAS_RGB24TOYROW_SSSE3 +#define HAS_RGB565TOARGBROW_SSE2 +#define HAS_RGBATOUVROW_SSSE3 +#define HAS_RGBATOYROW_SSSE3 +#define HAS_SETROW_ERMS +#define HAS_SETROW_X86 +#define HAS_SPLITUVROW_SSE2 +#define HAS_UYVYTOARGBROW_SSSE3 +#define HAS_UYVYTOUV422ROW_SSE2 +#define HAS_UYVYTOUVROW_SSE2 +#define HAS_UYVYTOYROW_SSE2 +#define HAS_YUY2TOARGBROW_SSSE3 +#define HAS_YUY2TOUV422ROW_SSE2 +#define HAS_YUY2TOUVROW_SSE2 +#define HAS_YUY2TOYROW_SSE2 + +// Effects: +#define HAS_ARGBADDROW_SSE2 +#define HAS_ARGBAFFINEROW_SSE2 +#define HAS_ARGBATTENUATEROW_SSSE3 +#define HAS_ARGBBLENDROW_SSSE3 +#define HAS_ARGBCOLORMATRIXROW_SSSE3 +#define HAS_ARGBCOLORTABLEROW_X86 +#define HAS_ARGBCOPYALPHAROW_SSE2 +#define HAS_ARGBCOPYYTOALPHAROW_SSE2 +#define HAS_ARGBGRAYROW_SSSE3 +#define HAS_ARGBLUMACOLORTABLEROW_SSSE3 +#define HAS_ARGBMIRRORROW_SSE2 +#define HAS_ARGBMULTIPLYROW_SSE2 +#define HAS_ARGBPOLYNOMIALROW_SSE2 +#define HAS_ARGBQUANTIZEROW_SSE2 +#define HAS_ARGBSEPIAROW_SSSE3 +#define HAS_ARGBSHADEROW_SSE2 +#define HAS_ARGBSUBTRACTROW_SSE2 +#define HAS_ARGBUNATTENUATEROW_SSE2 +#define HAS_COMPUTECUMULATIVESUMROW_SSE2 +#define HAS_CUMULATIVESUMTOAVERAGEROW_SSE2 +#define HAS_INTERPOLATEROW_SSSE3 +#define HAS_RGBCOLORTABLEROW_X86 +#define HAS_SOBELROW_SSE2 +#define HAS_SOBELTOPLANEROW_SSE2 +#define HAS_SOBELXROW_SSE2 +#define HAS_SOBELXYROW_SSE2 +#define HAS_SOBELYROW_SSE2 +#define HAS_BLENDPLANEROW_SSSE3 +#endif + // The following are available on all x86 platforms, but // require VS2012, clang 3.4 or gcc 4.7. // The code supports NaCL but requires a new compiler and validator. #if !defined(LIBYUV_DISABLE_X86) && (defined(VISUALC_HAS_AVX2) || \ defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) -// Effects: -#define HAS_ARGBPOLYNOMIALROW_AVX2 -#define HAS_ARGBSHUFFLEROW_AVX2 #define HAS_ARGBCOPYALPHAROW_AVX2 #define HAS_ARGBCOPYYTOALPHAROW_AVX2 -#endif - -// The following are require VS2012. -// TODO(fbarchard): Port to gcc. -#if !defined(LIBYUV_DISABLE_X86) && defined(VISUALC_HAS_AVX2) +#define HAS_ARGBMIRRORROW_AVX2 +#define HAS_ARGBPOLYNOMIALROW_AVX2 +#define HAS_ARGBSHUFFLEROW_AVX2 +#define HAS_ARGBTORGB565DITHERROW_AVX2 #define HAS_ARGBTOUVROW_AVX2 #define HAS_ARGBTOYJROW_AVX2 #define HAS_ARGBTOYROW_AVX2 -#define HAS_HALFROW_AVX2 +#define HAS_COPYROW_AVX +#define HAS_H422TOARGBROW_AVX2 +#define HAS_I400TOARGBROW_AVX2 +#if !(defined(_DEBUG) && defined(__i386__)) +// TODO(fbarchard): fix build error on android_full_debug=1 +// https://code.google.com/p/libyuv/issues/detail?id=517 +#define HAS_I422ALPHATOARGBROW_AVX2 +#endif +#define HAS_I444TOARGBROW_AVX2 #define HAS_I422TOARGBROW_AVX2 +#define HAS_I422TORGB24ROW_AVX2 +#define HAS_I422TORGBAROW_AVX2 #define HAS_INTERPOLATEROW_AVX2 +#define HAS_J422TOARGBROW_AVX2 #define HAS_MERGEUVROW_AVX2 #define HAS_MIRRORROW_AVX2 +#define HAS_NV12TOARGBROW_AVX2 +#define HAS_NV21TOARGBROW_AVX2 #define HAS_SPLITUVROW_AVX2 +#define HAS_UYVYTOARGBROW_AVX2 #define HAS_UYVYTOUV422ROW_AVX2 #define HAS_UYVYTOUVROW_AVX2 #define HAS_UYVYTOYROW_AVX2 +#define HAS_YUY2TOARGBROW_AVX2 #define HAS_YUY2TOUV422ROW_AVX2 #define HAS_YUY2TOUVROW_AVX2 #define HAS_YUY2TOYROW_AVX2 @@ -220,131 +230,41 @@ extern "C" { // Effects: #define HAS_ARGBADDROW_AVX2 #define HAS_ARGBATTENUATEROW_AVX2 -#define HAS_ARGBMIRRORROW_AVX2 #define HAS_ARGBMULTIPLYROW_AVX2 #define HAS_ARGBSUBTRACTROW_AVX2 #define HAS_ARGBUNATTENUATEROW_AVX2 -#endif // defined(VISUALC_HAS_AVX2) - -// The following are Yasm x86 only: -// TODO(fbarchard): Port AVX2 to inline. -#if !defined(LIBYUV_DISABLE_X86) && defined(HAVE_YASM) - (defined(_M_IX86) || defined(_M_X64) || \ - defined(__x86_64__) || defined(__i386__)) -#define HAS_MERGEUVROW_AVX2 -#define HAS_MERGEUVROW_MMX -#define HAS_SPLITUVROW_AVX2 -#define HAS_SPLITUVROW_MMX -#define HAS_UYVYTOYROW_AVX2 -#define HAS_UYVYTOYROW_MMX -#define HAS_YUY2TOYROW_AVX2 -#define HAS_YUY2TOYROW_MMX +#define HAS_BLENDPLANEROW_AVX2 #endif -// The following are disabled when SSSE3 is available: -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) && \ - !defined(LIBYUV_SSSE3_ONLY) -#define HAS_ARGBBLENDROW_SSE2 -#define HAS_ARGBATTENUATEROW_SSE2 -#define HAS_MIRRORROW_SSE2 +// The following are available for AVX2 Visual C and clangcl 32 bit: +// TODO(fbarchard): Port to gcc. +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && \ + (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) +#define HAS_ARGB1555TOARGBROW_AVX2 +#define HAS_ARGB4444TOARGBROW_AVX2 +#define HAS_ARGBTOARGB1555ROW_AVX2 +#define HAS_ARGBTOARGB4444ROW_AVX2 +#define HAS_ARGBTORGB565ROW_AVX2 +#define HAS_I411TOARGBROW_AVX2 +#define HAS_I422TOARGB1555ROW_AVX2 +#define HAS_I422TOARGB4444ROW_AVX2 +#define HAS_I422TORGB565ROW_AVX2 +#define HAS_J400TOARGBROW_AVX2 +#define HAS_NV12TORGB565ROW_AVX2 +#define HAS_RGB565TOARGBROW_AVX2 #endif -// The following are available on arm64 platforms: -#if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) -// #define HAS_I444TOARGBROW_NEON -// #define HAS_I422TOARGBROW_NEON -// #define HAS_I411TOARGBROW_NEON -// #define HAS_I422TOBGRAROW_NEON -// #define HAS_I422TOABGRROW_NEON -// #define HAS_I422TORGBAROW_NEON -// #define HAS_I422TORGB24ROW_NEON -// #define HAS_I422TORAWROW_NEON -// #define HAS_I422TORGB565ROW_NEON -// #define HAS_I422TOARGB1555ROW_NEON -// #define HAS_I422TOARGB4444ROW_NEON -// #define HAS_YTOARGBROW_NEON -// #define HAS_I400TOARGBROW_NEON -// #define HAS_NV12TOARGBROW_NEON -// #define HAS_NV21TOARGBROW_NEON -// #define HAS_NV12TORGB565ROW_NEON -// #define HAS_NV21TORGB565ROW_NEON -// #define HAS_YUY2TOARGBROW_NEON -// #define HAS_UYVYTOARGBROW_NEON -#define HAS_SPLITUVROW_NEON -#define HAS_MERGEUVROW_NEON -#define HAS_COPYROW_NEON -#define HAS_SETROW_NEON -#define HAS_ARGBSETROWS_NEON -#define HAS_MIRRORROW_NEON -#define HAS_MIRRORUVROW_NEON -#define HAS_ARGBMIRRORROW_NEON -#define HAS_RGB24TOARGBROW_NEON -#define HAS_RAWTOARGBROW_NEON -// #define HAS_RGB565TOARGBROW_NEON -// #define HAS_ARGB1555TOARGBROW_NEON -// #define HAS_ARGB4444TOARGBROW_NEON -#define HAS_ARGBTORGB24ROW_NEON -#define HAS_ARGBTORAWROW_NEON -#define HAS_YUY2TOYROW_NEON -#define HAS_UYVYTOYROW_NEON -#define HAS_YUY2TOUV422ROW_NEON -#define HAS_UYVYTOUV422ROW_NEON -#define HAS_YUY2TOUVROW_NEON -#define HAS_UYVYTOUVROW_NEON -#define HAS_HALFROW_NEON -#define HAS_ARGBTOBAYERROW_NEON -#define HAS_ARGBTOBAYERGGROW_NEON -#define HAS_ARGBSHUFFLEROW_NEON -#define HAS_I422TOYUY2ROW_NEON -#define HAS_I422TOUYVYROW_NEON -// #define HAS_ARGBTORGB565ROW_NEON -// #define HAS_ARGBTOARGB1555ROW_NEON -// #define HAS_ARGBTOARGB4444ROW_NEON -#define HAS_ARGBTOYROW_NEON -#define HAS_ARGBTOYJROW_NEON -#define HAS_ARGBTOUV444ROW_NEON -#define HAS_ARGBTOUV422ROW_NEON -#define HAS_ARGBTOUV411ROW_NEON -// #define HAS_ARGBTOUVROW_NEON -// #define HAS_ARGBTOUVJROW_NEON -// #define HAS_BGRATOUVROW_NEON -// #define HAS_ABGRTOUVROW_NEON -// #define HAS_RGBATOUVROW_NEON -// #define HAS_RGB24TOUVROW_NEON -// #define HAS_RAWTOUVROW_NEON -// #define HAS_RGB565TOUVROW_NEON -// #define HAS_ARGB1555TOUVROW_NEON -// #define HAS_ARGB4444TOUVROW_NEON -// #define HAS_RGB565TOYROW_NEON -// #define HAS_ARGB1555TOYROW_NEON -// #define HAS_ARGB4444TOYROW_NEON -#define HAS_BGRATOYROW_NEON -#define HAS_ABGRTOYROW_NEON -#define HAS_RGBATOYROW_NEON -#define HAS_RGB24TOYROW_NEON -#define HAS_RAWTOYROW_NEON -#define HAS_INTERPOLATEROW_NEON -#define HAS_ARGBBLENDROW_NEON -#define HAS_ARGBATTENUATEROW_NEON -#define HAS_ARGBQUANTIZEROW_NEON -#define HAS_ARGBSHADEROW_NEON -#define HAS_ARGBGRAYROW_NEON -#define HAS_ARGBSEPIAROW_NEON -#define HAS_ARGBCOLORMATRIXROW_NEON -#define HAS_ARGBMULTIPLYROW_NEON -#define HAS_ARGBADDROW_NEON -#define HAS_ARGBSUBTRACTROW_NEON -#define HAS_SOBELROW_NEON -#define HAS_SOBELTOPLANEROW_NEON -#define HAS_SOBELXYROW_NEON -#define HAS_SOBELXROW_NEON -#define HAS_SOBELYROW_NEON +// The following are also available on x64 Visual C. +#if !defined(LIBYUV_DISABLE_X86) && defined (_M_X64) && \ + (!defined(__clang__) || defined(__SSSE3__)) +#define HAS_I422ALPHATOARGBROW_SSSE3 +#define HAS_I422TOARGBROW_SSSE3 #endif // The following are available on Neon platforms: #if !defined(LIBYUV_DISABLE_NEON) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) + (defined(__aarch64__) || defined(__ARM_NEON__) || defined(LIBYUV_NEON)) +#define HAS_I422ALPHATOARGBROW_NEON #define HAS_ABGRTOUVROW_NEON #define HAS_ABGRTOYROW_NEON #define HAS_ARGB1555TOARGBROW_NEON @@ -353,46 +273,43 @@ extern "C" { #define HAS_ARGB4444TOARGBROW_NEON #define HAS_ARGB4444TOUVROW_NEON #define HAS_ARGB4444TOYROW_NEON +#define HAS_ARGBSETROW_NEON #define HAS_ARGBTOARGB1555ROW_NEON #define HAS_ARGBTOARGB4444ROW_NEON -#define HAS_ARGBTOBAYERROW_NEON -#define HAS_ARGBTOBAYERGGROW_NEON #define HAS_ARGBTORAWROW_NEON #define HAS_ARGBTORGB24ROW_NEON +#define HAS_ARGBTORGB565DITHERROW_NEON #define HAS_ARGBTORGB565ROW_NEON #define HAS_ARGBTOUV411ROW_NEON #define HAS_ARGBTOUV422ROW_NEON #define HAS_ARGBTOUV444ROW_NEON -#define HAS_ARGBTOUVROW_NEON #define HAS_ARGBTOUVJROW_NEON -#define HAS_ARGBTOYROW_NEON +#define HAS_ARGBTOUVROW_NEON #define HAS_ARGBTOYJROW_NEON +#define HAS_ARGBTOYROW_NEON #define HAS_BGRATOUVROW_NEON #define HAS_BGRATOYROW_NEON #define HAS_COPYROW_NEON -#define HAS_HALFROW_NEON #define HAS_I400TOARGBROW_NEON #define HAS_I411TOARGBROW_NEON -#define HAS_I422TOABGRROW_NEON #define HAS_I422TOARGB1555ROW_NEON #define HAS_I422TOARGB4444ROW_NEON #define HAS_I422TOARGBROW_NEON -#define HAS_I422TOBGRAROW_NEON -#define HAS_I422TORAWROW_NEON #define HAS_I422TORGB24ROW_NEON #define HAS_I422TORGB565ROW_NEON #define HAS_I422TORGBAROW_NEON #define HAS_I422TOUYVYROW_NEON #define HAS_I422TOYUY2ROW_NEON #define HAS_I444TOARGBROW_NEON +#define HAS_J400TOARGBROW_NEON #define HAS_MERGEUVROW_NEON #define HAS_MIRRORROW_NEON #define HAS_MIRRORUVROW_NEON #define HAS_NV12TOARGBROW_NEON #define HAS_NV12TORGB565ROW_NEON #define HAS_NV21TOARGBROW_NEON -#define HAS_NV21TORGB565ROW_NEON #define HAS_RAWTOARGBROW_NEON +#define HAS_RAWTORGB24ROW_NEON #define HAS_RAWTOUVROW_NEON #define HAS_RAWTOYROW_NEON #define HAS_RGB24TOARGBROW_NEON @@ -409,7 +326,6 @@ extern "C" { #define HAS_UYVYTOUV422ROW_NEON #define HAS_UYVYTOUVROW_NEON #define HAS_UYVYTOYROW_NEON -#define HAS_YTOARGBROW_NEON #define HAS_YUY2TOARGBROW_NEON #define HAS_YUY2TOUV422ROW_NEON #define HAS_YUY2TOUVROW_NEON @@ -419,21 +335,21 @@ extern "C" { #define HAS_ARGBADDROW_NEON #define HAS_ARGBATTENUATEROW_NEON #define HAS_ARGBBLENDROW_NEON +#define HAS_ARGBCOLORMATRIXROW_NEON #define HAS_ARGBGRAYROW_NEON #define HAS_ARGBMIRRORROW_NEON #define HAS_ARGBMULTIPLYROW_NEON #define HAS_ARGBQUANTIZEROW_NEON #define HAS_ARGBSEPIAROW_NEON #define HAS_ARGBSHADEROW_NEON +#define HAS_ARGBSHUFFLEROW_NEON #define HAS_ARGBSUBTRACTROW_NEON +#define HAS_INTERPOLATEROW_NEON #define HAS_SOBELROW_NEON #define HAS_SOBELTOPLANEROW_NEON -#define HAS_SOBELXYROW_NEON #define HAS_SOBELXROW_NEON +#define HAS_SOBELXYROW_NEON #define HAS_SOBELYROW_NEON -#define HAS_INTERPOLATEROW_NEON -// TODO(fbarchard): Investigate neon unittest failure. -// #define HAS_ARGBCOLORMATRIXROW_NEON #endif // The following are available on Mips platforms: @@ -441,10 +357,8 @@ extern "C" { (_MIPS_SIM == _MIPS_SIM_ABI32) && (__mips_isa_rev < 6) #define HAS_COPYROW_MIPS #if defined(__mips_dsp) && (__mips_dsp_rev >= 2) -#define HAS_I422TOABGRROW_MIPS_DSPR2 #define HAS_I422TOARGBROW_MIPS_DSPR2 -#define HAS_I422TOBGRAROW_MIPS_DSPR2 -#define HAS_INTERPOLATEROWS_MIPS_DSPR2 +#define HAS_INTERPOLATEROW_MIPS_DSPR2 #define HAS_MIRRORROW_MIPS_DSPR2 #define HAS_MIRRORUVROW_MIPS_DSPR2 #define HAS_SPLITUVROW_MIPS_DSPR2 @@ -453,6 +367,7 @@ extern "C" { #if defined(_MSC_VER) && !defined(__CLR_VER) #define SIMD_ALIGNED(var) __declspec(align(16)) var +#define SIMD_ALIGNED32(var) __declspec(align(64)) var typedef __declspec(align(16)) int16 vec16[8]; typedef __declspec(align(16)) int32 vec32[4]; typedef __declspec(align(16)) int8 vec8[16]; @@ -465,26 +380,89 @@ typedef __declspec(align(32)) int8 lvec8[32]; typedef __declspec(align(32)) uint16 ulvec16[16]; typedef __declspec(align(32)) uint32 ulvec32[8]; typedef __declspec(align(32)) uint8 ulvec8[32]; - -#elif defined(__GNUC__) +#elif defined(__GNUC__) && !defined(__pnacl__) // Caveat GCC 4.2 to 4.7 have a known issue using vectors with const. #define SIMD_ALIGNED(var) var __attribute__((aligned(16))) +#define SIMD_ALIGNED32(var) var __attribute__((aligned(64))) typedef int16 __attribute__((vector_size(16))) vec16; typedef int32 __attribute__((vector_size(16))) vec32; typedef int8 __attribute__((vector_size(16))) vec8; typedef uint16 __attribute__((vector_size(16))) uvec16; typedef uint32 __attribute__((vector_size(16))) uvec32; typedef uint8 __attribute__((vector_size(16))) uvec8; +typedef int16 __attribute__((vector_size(32))) lvec16; +typedef int32 __attribute__((vector_size(32))) lvec32; +typedef int8 __attribute__((vector_size(32))) lvec8; +typedef uint16 __attribute__((vector_size(32))) ulvec16; +typedef uint32 __attribute__((vector_size(32))) ulvec32; +typedef uint8 __attribute__((vector_size(32))) ulvec8; #else #define SIMD_ALIGNED(var) var +#define SIMD_ALIGNED32(var) var typedef int16 vec16[8]; typedef int32 vec32[4]; typedef int8 vec8[16]; typedef uint16 uvec16[8]; typedef uint32 uvec32[4]; typedef uint8 uvec8[16]; +typedef int16 lvec16[16]; +typedef int32 lvec32[8]; +typedef int8 lvec8[32]; +typedef uint16 ulvec16[16]; +typedef uint32 ulvec32[8]; +typedef uint8 ulvec8[32]; #endif +#if defined(__aarch64__) +// This struct is for Arm64 color conversion. +struct YuvConstants { + uvec16 kUVToRB; + uvec16 kUVToRB2; + uvec16 kUVToG; + uvec16 kUVToG2; + vec16 kUVBiasBGR; + vec32 kYToRgb; +}; +#elif defined(__arm__) +// This struct is for ArmV7 color conversion. +struct YuvConstants { + uvec8 kUVToRB; + uvec8 kUVToG; + vec16 kUVBiasBGR; + vec32 kYToRgb; +}; +#else +// This struct is for Intel color conversion. +struct YuvConstants { + lvec8 kUVToB; + lvec8 kUVToG; + lvec8 kUVToR; + lvec16 kUVBiasB; + lvec16 kUVBiasG; + lvec16 kUVBiasR; + lvec16 kYToRgb; +}; + +// Offsets into YuvConstants structure +#define KUVTOB 0 +#define KUVTOG 32 +#define KUVTOR 64 +#define KUVBIASB 96 +#define KUVBIASG 128 +#define KUVBIASR 160 +#define KYTORGB 192 +#endif + +// Conversion matrix for YUV to RGB +extern const struct YuvConstants kYuvI601Constants; // BT.601 +extern const struct YuvConstants kYuvJPEGConstants; // JPeg color space +extern const struct YuvConstants kYuvH709Constants; // BT.709 + +// Conversion matrix for YVU to BGR +extern const struct YuvConstants kYvuI601Constants; // BT.601 +extern const struct YuvConstants kYvuJPEGConstants; // JPeg color space +extern const struct YuvConstants kYvuH709Constants; // BT.709 + #if defined(__APPLE__) || defined(__x86_64__) || defined(__llvm__) #define OMITFP #else @@ -492,24 +470,16 @@ typedef uint8 uvec8[16]; #endif // NaCL macros for GCC x86 and x64. - -// TODO(nfullagar): When pepper_33 toolchain is distributed, default to -// NEW_BINUTILS and remove all BUNDLEALIGN occurances. #if defined(__native_client__) #define LABELALIGN ".p2align 5\n" #else -#define LABELALIGN ".p2align 2\n" +#define LABELALIGN #endif #if defined(__native_client__) && defined(__x86_64__) -#if defined(NEW_BINUTILS) +// r14 is used for MEMOP macros. +#define NACL_R14 "r14", #define BUNDLELOCK ".bundle_lock\n" #define BUNDLEUNLOCK ".bundle_unlock\n" -#define BUNDLEALIGN "\n" -#else -#define BUNDLELOCK "\n" -#define BUNDLEUNLOCK "\n" -#define BUNDLEALIGN ".p2align 5\n" -#endif #define MEMACCESS(base) "%%nacl:(%%r15,%q" #base ")" #define MEMACCESS2(offset, base) "%%nacl:" #offset "(%%r15,%q" #base ")" #define MEMLEA(offset, base) #offset "(%q" #base ")" @@ -534,8 +504,19 @@ typedef uint8 uvec8[16]; "lea " #offset "(%q" #base ",%q" #index "," #scale "),%%r14d\n" \ #opcode " (%%r15,%%r14),%" #arg "\n" \ BUNDLEUNLOCK +#define VMEMOPREG(opcode, offset, base, index, scale, reg1, reg2) \ + BUNDLELOCK \ + "lea " #offset "(%q" #base ",%q" #index "," #scale "),%%r14d\n" \ + #opcode " (%%r15,%%r14),%%" #reg1 ",%%" #reg2 "\n" \ + BUNDLEUNLOCK +#define VEXTOPMEM(op, sel, reg, offset, base, index, scale) \ + BUNDLELOCK \ + "lea " #offset "(%q" #base ",%q" #index "," #scale "),%%r14d\n" \ + #op " $" #sel ",%%" #reg ",(%%r15,%%r14)\n" \ + BUNDLEUNLOCK #else // defined(__native_client__) && defined(__x86_64__) -#define BUNDLEALIGN "\n" +#define NACL_R14 +#define BUNDLEALIGN #define MEMACCESS(base) "(%" #base ")" #define MEMACCESS2(offset, base) #offset "(%" #base ")" #define MEMLEA(offset, base) #offset "(%" #base ")" @@ -551,14 +532,19 @@ typedef uint8 uvec8[16]; #opcode " %%" #reg ","#offset "(%" #base ",%" #index "," #scale ")\n" #define MEMOPARG(opcode, offset, base, index, scale, arg) \ #opcode " " #offset "(%" #base ",%" #index "," #scale "),%" #arg "\n" +#define VMEMOPREG(opcode, offset, base, index, scale, reg1, reg2) \ + #opcode " " #offset "(%" #base ",%" #index "," #scale "),%%" #reg1 ",%%" \ + #reg2 "\n" +#define VEXTOPMEM(op, sel, reg, offset, base, index, scale) \ + #op " $" #sel ",%%" #reg ","#offset "(%" #base ",%" #index "," #scale ")\n" #endif // defined(__native_client__) && defined(__x86_64__) #if defined(__arm__) || defined(__aarch64__) #undef MEMACCESS #if defined(__native_client__) -#define MEMACCESS(base) ".p2align 3\nbic %" #base ", #0xc0000000\n" +#define MEMACCESS(base) ".p2align 3\nbic %" #base ", #0xc0000000\n" #else -#define MEMACCESS(base) "\n" +#define MEMACCESS(base) #endif #endif @@ -566,161 +552,163 @@ void I444ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_NEON(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_NEON(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I411ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, - int width); -void I422ToBGRARow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width); -void I422ToABGRRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, + const struct YuvConstants* yuvconstants, int width); void I422ToRGBARow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); void I422ToRGB24Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width); -void I422ToRAWRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_raw, - int width); void I422ToRGB565Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB1555Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB4444Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width); void NV12ToARGBRow_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, - int width); -void NV21ToARGBRow_NEON(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV12ToRGB565Row_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width); -void NV21ToRGB565Row_NEON(const uint8* src_y, - const uint8* src_vu, - uint8* dst_rgb565, - int width); +void NV21ToARGBRow_NEON(const uint8* src_y, + const uint8* src_vu, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void YUY2ToARGBRow_NEON(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void UYVYToARGBRow_NEON(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYRow_Any_AVX2(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_Any_AVX2(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void BGRAToYRow_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); -void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void BGRAToYRow_Unaligned_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_Unaligned_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_Unaligned_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_Unaligned_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_Unaligned_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); -void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYRow_Any_AVX2(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_Any_AVX2(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width); +void BGRAToYRow_SSSE3(const uint8* src_bgra, uint8* dst_y, int width); +void ABGRToYRow_SSSE3(const uint8* src_abgr, uint8* dst_y, int width); +void RGBAToYRow_SSSE3(const uint8* src_rgba, uint8* dst_y, int width); +void RGB24ToYRow_SSSE3(const uint8* src_rgb24, uint8* dst_y, int width); +void RAWToYRow_SSSE3(const uint8* src_raw, uint8* dst_y, int width); +void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int width); void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RAWToUVRow_NEON(const uint8* src_raw, int src_stride_raw, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGB565ToUVRow_NEON(const uint8* src_rgb565, int src_stride_rgb565, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGB1555ToUVRow_NEON(const uint8* src_argb1555, int src_stride_argb1555, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGB4444ToUVRow_NEON(const uint8* src_argb4444, int src_stride_argb4444, - uint8* dst_u, uint8* dst_v, int pix); -void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix); -void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int pix); -void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int pix); -void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int pix); -void ARGBToYRow_C(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_C(const uint8* src_argb, uint8* dst_y, int pix); -void BGRAToYRow_C(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_C(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_C(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_C(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_C(const uint8* src_raw, uint8* dst_y, int pix); -void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int pix); -void ARGB1555ToYRow_C(const uint8* src_argb1555, uint8* dst_y, int pix); -void ARGB4444ToYRow_C(const uint8* src_argb4444, uint8* dst_y, int pix); -void ARGBToYRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); -void BGRAToYRow_Any_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_Any_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_Any_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_Any_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_Any_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); -void ARGBToYRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int pix); -void ARGBToYJRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int pix); -void BGRAToYRow_Any_NEON(const uint8* src_bgra, uint8* dst_y, int pix); -void ABGRToYRow_Any_NEON(const uint8* src_abgr, uint8* dst_y, int pix); -void RGBAToYRow_Any_NEON(const uint8* src_rgba, uint8* dst_y, int pix); -void RGB24ToYRow_Any_NEON(const uint8* src_rgb24, uint8* dst_y, int pix); -void RAWToYRow_Any_NEON(const uint8* src_raw, uint8* dst_y, int pix); -void RGB565ToYRow_Any_NEON(const uint8* src_rgb565, uint8* dst_y, int pix); -void ARGB1555ToYRow_Any_NEON(const uint8* src_argb1555, uint8* dst_y, int pix); -void ARGB4444ToYRow_Any_NEON(const uint8* src_argb4444, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int width); +void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int width); +void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int width); +void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int width); +void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int width); +void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int width); +void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int width); +void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int width); +void ARGBToYRow_C(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_C(const uint8* src_argb, uint8* dst_y, int width); +void BGRAToYRow_C(const uint8* src_bgra, uint8* dst_y, int width); +void ABGRToYRow_C(const uint8* src_abgr, uint8* dst_y, int width); +void RGBAToYRow_C(const uint8* src_rgba, uint8* dst_y, int width); +void RGB24ToYRow_C(const uint8* src_rgb24, uint8* dst_y, int width); +void RAWToYRow_C(const uint8* src_raw, uint8* dst_y, int width); +void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int width); +void ARGB1555ToYRow_C(const uint8* src_argb1555, uint8* dst_y, int width); +void ARGB4444ToYRow_C(const uint8* src_argb4444, uint8* dst_y, int width); +void ARGBToYRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int width); +void BGRAToYRow_Any_SSSE3(const uint8* src_bgra, uint8* dst_y, int width); +void ABGRToYRow_Any_SSSE3(const uint8* src_abgr, uint8* dst_y, int width); +void RGBAToYRow_Any_SSSE3(const uint8* src_rgba, uint8* dst_y, int width); +void RGB24ToYRow_Any_SSSE3(const uint8* src_rgb24, uint8* dst_y, int width); +void RAWToYRow_Any_SSSE3(const uint8* src_raw, uint8* dst_y, int width); +void ARGBToYRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYJRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int width); +void BGRAToYRow_Any_NEON(const uint8* src_bgra, uint8* dst_y, int width); +void ABGRToYRow_Any_NEON(const uint8* src_abgr, uint8* dst_y, int width); +void RGBAToYRow_Any_NEON(const uint8* src_rgba, uint8* dst_y, int width); +void RGB24ToYRow_Any_NEON(const uint8* src_rgb24, uint8* dst_y, int width); +void RAWToYRow_Any_NEON(const uint8* src_raw, uint8* dst_y, int width); +void RGB565ToYRow_Any_NEON(const uint8* src_rgb565, uint8* dst_y, int width); +void ARGB1555ToYRow_Any_NEON(const uint8* src_argb1555, uint8* dst_y, + int width); +void ARGB4444ToYRow_Any_NEON(const uint8* src_argb4444, uint8* dst_y, + int width); void ARGBToUVRow_AVX2(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); @@ -736,16 +724,6 @@ void ABGRToUVRow_SSSE3(const uint8* src_abgr, int src_stride_abgr, uint8* dst_u, uint8* dst_v, int width); void RGBAToUVRow_SSSE3(const uint8* src_rgba, int src_stride_rgba, uint8* dst_u, uint8* dst_v, int width); -void ARGBToUVRow_Unaligned_SSSE3(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width); -void ARGBToUVJRow_Unaligned_SSSE3(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width); -void BGRAToUVRow_Unaligned_SSSE3(const uint8* src_bgra, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int width); -void ABGRToUVRow_Unaligned_SSSE3(const uint8* src_abgr, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int width); -void RGBAToUVRow_Unaligned_SSSE3(const uint8* src_rgba, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int width); void ARGBToUVRow_Any_SSSE3(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_Any_SSSE3(const uint8* src_argb, int src_stride_argb, @@ -757,33 +735,33 @@ void ABGRToUVRow_Any_SSSE3(const uint8* src_abgr, int src_stride_abgr, void RGBAToUVRow_Any_SSSE3(const uint8* src_rgba, int src_stride_rgba, uint8* dst_u, uint8* dst_v, int width); void ARGBToUV444Row_Any_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUV422Row_Any_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUV411Row_Any_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix); + int width); void ARGBToUVRow_Any_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_Any_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void BGRAToUVRow_Any_NEON(const uint8* src_bgra, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ABGRToUVRow_Any_NEON(const uint8* src_abgr, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGBAToUVRow_Any_NEON(const uint8* src_rgba, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGB24ToUVRow_Any_NEON(const uint8* src_rgb24, int src_stride_rgb24, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RAWToUVRow_Any_NEON(const uint8* src_raw, int src_stride_raw, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void RGB565ToUVRow_Any_NEON(const uint8* src_rgb565, int src_stride_rgb565, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGB1555ToUVRow_Any_NEON(const uint8* src_argb1555, int src_stride_argb1555, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGB4444ToUVRow_Any_NEON(const uint8* src_argb4444, int src_stride_argb4444, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void ARGBToUVRow_C(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_C(const uint8* src_argb, int src_stride_argb, @@ -807,15 +785,11 @@ void ARGB4444ToUVRow_C(const uint8* src_argb4444, int src_stride_argb4444, void ARGBToUV444Row_SSSE3(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); -void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb, - uint8* dst_u, uint8* dst_v, int width); void ARGBToUV444Row_Any_SSSE3(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUV422Row_SSSE3(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); -void ARGBToUV422Row_Unaligned_SSSE3(const uint8* src_argb, - uint8* dst_u, uint8* dst_v, int width); void ARGBToUV422Row_Any_SSSE3(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); @@ -825,13 +799,18 @@ void ARGBToUV422Row_C(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUV411Row_C(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); +void ARGBToUVJ422Row_C(const uint8* src_argb, + uint8* dst_u, uint8* dst_v, int width); void MirrorRow_AVX2(const uint8* src, uint8* dst, int width); void MirrorRow_SSSE3(const uint8* src, uint8* dst, int width); -void MirrorRow_SSE2(const uint8* src, uint8* dst, int width); void MirrorRow_NEON(const uint8* src, uint8* dst, int width); void MirrorRow_MIPS_DSPR2(const uint8* src, uint8* dst, int width); void MirrorRow_C(const uint8* src, uint8* dst, int width); +void MirrorRow_Any_AVX2(const uint8* src, uint8* dst, int width); +void MirrorRow_Any_SSSE3(const uint8* src, uint8* dst, int width); +void MirrorRow_Any_SSE2(const uint8* src, uint8* dst, int width); +void MirrorRow_Any_NEON(const uint8* src, uint8* dst, int width); void MirrorUVRow_SSSE3(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width); @@ -843,28 +822,30 @@ void MirrorUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width); void ARGBMirrorRow_AVX2(const uint8* src, uint8* dst, int width); -void ARGBMirrorRow_SSSE3(const uint8* src, uint8* dst, int width); +void ARGBMirrorRow_SSE2(const uint8* src, uint8* dst, int width); void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width); void ARGBMirrorRow_C(const uint8* src, uint8* dst, int width); +void ARGBMirrorRow_Any_AVX2(const uint8* src, uint8* dst, int width); +void ARGBMirrorRow_Any_SSE2(const uint8* src, uint8* dst, int width); +void ARGBMirrorRow_Any_NEON(const uint8* src, uint8* dst, int width); -void SplitUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix); -void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix); -void SplitUVRow_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix); -void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix); +void SplitUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width); +void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width); +void SplitUVRow_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width); +void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width); void SplitUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); -void SplitUVRow_Unaligned_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); -void SplitUVRow_Unaligned_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, - uint8* dst_v, int pix); + int width); void SplitUVRow_Any_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); + int width); void SplitUVRow_Any_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); + int width); void SplitUVRow_Any_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); + int width); void SplitUVRow_Any_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix); + int width); void MergeUVRow_C(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width); @@ -874,8 +855,6 @@ void MergeUVRow_AVX2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width); void MergeUVRow_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width); -void MergeUVRow_Unaligned_SSE2(const uint8* src_u, const uint8* src_v, - uint8* dst_uv, int width); void MergeUVRow_Any_SSE2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width); void MergeUVRow_Any_AVX2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, @@ -884,431 +863,611 @@ void MergeUVRow_Any_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width); void CopyRow_SSE2(const uint8* src, uint8* dst, int count); +void CopyRow_AVX(const uint8* src, uint8* dst, int count); void CopyRow_ERMS(const uint8* src, uint8* dst, int count); -void CopyRow_X86(const uint8* src, uint8* dst, int count); void CopyRow_NEON(const uint8* src, uint8* dst, int count); void CopyRow_MIPS(const uint8* src, uint8* dst, int count); void CopyRow_C(const uint8* src, uint8* dst, int count); +void CopyRow_Any_SSE2(const uint8* src, uint8* dst, int count); +void CopyRow_Any_AVX(const uint8* src, uint8* dst, int count); +void CopyRow_Any_NEON(const uint8* src, uint8* dst, int count); void CopyRow_16_C(const uint16* src, uint16* dst, int count); void ARGBCopyAlphaRow_C(const uint8* src_argb, uint8* dst_argb, int width); void ARGBCopyAlphaRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width); void ARGBCopyAlphaRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width); +void ARGBCopyAlphaRow_Any_SSE2(const uint8* src_argb, uint8* dst_argb, + int width); +void ARGBCopyAlphaRow_Any_AVX2(const uint8* src_argb, uint8* dst_argb, + int width); void ARGBCopyYToAlphaRow_C(const uint8* src_y, uint8* dst_argb, int width); void ARGBCopyYToAlphaRow_SSE2(const uint8* src_y, uint8* dst_argb, int width); void ARGBCopyYToAlphaRow_AVX2(const uint8* src_y, uint8* dst_argb, int width); +void ARGBCopyYToAlphaRow_Any_SSE2(const uint8* src_y, uint8* dst_argb, + int width); +void ARGBCopyYToAlphaRow_Any_AVX2(const uint8* src_y, uint8* dst_argb, + int width); -void SetRow_X86(uint8* dst, uint32 v32, int count); -void ARGBSetRows_X86(uint8* dst, uint32 v32, int width, - int dst_stride, int height); -void SetRow_NEON(uint8* dst, uint32 v32, int count); -void ARGBSetRows_NEON(uint8* dst, uint32 v32, int width, - int dst_stride, int height); -void SetRow_C(uint8* dst, uint32 v32, int count); -void ARGBSetRows_C(uint8* dst, uint32 v32, int width, int dst_stride, - int height); +void SetRow_C(uint8* dst, uint8 v8, int count); +void SetRow_X86(uint8* dst, uint8 v8, int count); +void SetRow_ERMS(uint8* dst, uint8 v8, int count); +void SetRow_NEON(uint8* dst, uint8 v8, int count); +void SetRow_Any_X86(uint8* dst, uint8 v8, int count); +void SetRow_Any_NEON(uint8* dst, uint8 v8, int count); + +void ARGBSetRow_C(uint8* dst_argb, uint32 v32, int count); +void ARGBSetRow_X86(uint8* dst_argb, uint32 v32, int count); +void ARGBSetRow_NEON(uint8* dst_argb, uint32 v32, int count); +void ARGBSetRow_Any_NEON(uint8* dst_argb, uint32 v32, int count); // ARGBShufflers for BGRAToARGB etc. void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_AVX2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_NEON(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); -void ARGBShuffleRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_Any_SSE2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_Any_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_Any_AVX2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); void ARGBShuffleRow_Any_NEON(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix); + const uint8* shuffler, int width); -void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix); -void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, int pix); -void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, int pix); +void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int width); +void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, int width); +void RAWToRGB24Row_SSSE3(const uint8* src_raw, uint8* dst_rgb24, int width); +void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, int width); void ARGB1555ToARGBRow_SSE2(const uint8* src_argb1555, uint8* dst_argb, - int pix); + int width); void ARGB4444ToARGBRow_SSE2(const uint8* src_argb4444, uint8* dst_argb, - int pix); + int width); +void RGB565ToARGBRow_AVX2(const uint8* src_rgb565, uint8* dst_argb, int width); +void ARGB1555ToARGBRow_AVX2(const uint8* src_argb1555, uint8* dst_argb, + int width); +void ARGB4444ToARGBRow_AVX2(const uint8* src_argb4444, uint8* dst_argb, + int width); -void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix); -void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int pix); -void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int pix); +void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int width); +void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int width); +void RAWToRGB24Row_NEON(const uint8* src_raw, uint8* dst_rgb24, int width); +void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int width); void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, - int pix); + int width); void ARGB4444ToARGBRow_NEON(const uint8* src_argb4444, uint8* dst_argb, - int pix); -void RGB24ToARGBRow_C(const uint8* src_rgb24, uint8* dst_argb, int pix); -void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int pix); -void RGB565ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int pix); -void ARGB1555ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int pix); -void ARGB4444ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int pix); -void RGB24ToARGBRow_Any_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix); -void RAWToARGBRow_Any_SSSE3(const uint8* src_raw, uint8* dst_argb, int pix); + int width); +void RGB24ToARGBRow_C(const uint8* src_rgb24, uint8* dst_argb, int width); +void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int width); +void RAWToRGB24Row_C(const uint8* src_raw, uint8* dst_rgb24, int width); +void RGB565ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int width); +void ARGB1555ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width); +void ARGB4444ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width); +void RGB24ToARGBRow_Any_SSSE3(const uint8* src_rgb24, uint8* dst_argb, + int width); +void RAWToARGBRow_Any_SSSE3(const uint8* src_raw, uint8* dst_argb, int width); +void RAWToRGB24Row_Any_SSSE3(const uint8* src_raw, uint8* dst_rgb24, int width); + void RGB565ToARGBRow_Any_SSE2(const uint8* src_rgb565, uint8* dst_argb, - int pix); + int width); void ARGB1555ToARGBRow_Any_SSE2(const uint8* src_argb1555, uint8* dst_argb, - int pix); + int width); void ARGB4444ToARGBRow_Any_SSE2(const uint8* src_argb4444, uint8* dst_argb, - int pix); -void RGB24ToARGBRow_Any_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix); -void RAWToARGBRow_Any_NEON(const uint8* src_raw, uint8* dst_argb, int pix); + int width); +void RGB565ToARGBRow_Any_AVX2(const uint8* src_rgb565, uint8* dst_argb, + int width); +void ARGB1555ToARGBRow_Any_AVX2(const uint8* src_argb1555, uint8* dst_argb, + int width); +void ARGB4444ToARGBRow_Any_AVX2(const uint8* src_argb4444, uint8* dst_argb, + int width); + +void RGB24ToARGBRow_Any_NEON(const uint8* src_rgb24, uint8* dst_argb, + int width); +void RAWToARGBRow_Any_NEON(const uint8* src_raw, uint8* dst_argb, int width); +void RAWToRGB24Row_Any_NEON(const uint8* src_raw, uint8* dst_rgb24, int width); void RGB565ToARGBRow_Any_NEON(const uint8* src_rgb565, uint8* dst_argb, - int pix); + int width); void ARGB1555ToARGBRow_Any_NEON(const uint8* src_argb1555, uint8* dst_argb, - int pix); + int width); void ARGB4444ToARGBRow_Any_NEON(const uint8* src_argb4444, uint8* dst_argb, - int pix); + int width); -void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width); -void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB4444Row_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGB565DitherRow_C(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); +void ARGBToRGB565DitherRow_SSE2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); +void ARGBToRGB565DitherRow_AVX2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); -void ARGBToRGBARow_C(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGB565Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB4444Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width); -void I400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int pix); -void I400ToARGBRow_Unaligned_SSE2(const uint8* src_y, uint8* dst_argb, int pix); -void I400ToARGBRow_NEON(const uint8* src_y, uint8* dst_argb, int pix); -void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int pix); -void I400ToARGBRow_Any_SSE2(const uint8* src_y, uint8* dst_argb, int pix); -void I400ToARGBRow_Any_NEON(const uint8* src_y, uint8* dst_argb, int pix); +void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB4444Row_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565DitherRow_NEON(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); + +void ARGBToRGBARow_C(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width); + +void J400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_AVX2(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_NEON(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_Any_SSE2(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_Any_AVX2(const uint8* src_y, uint8* dst_argb, int width); +void J400ToARGBRow_Any_NEON(const uint8* src_y, uint8* dst_argb, int width); void I444ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I422ToARGBRow_C(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_C(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I411ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV12ToARGBRow_C(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void NV21ToRGB565Row_C(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, - int width); void NV12ToRGB565Row_C(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV21ToARGBRow_C(const uint8* src_y, - const uint8* src_vu, + const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void YUY2ToARGBRow_C(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void UYVYToARGBRow_C(const uint8* src_uyvy, uint8* dst_argb, - int width); -void I422ToBGRARow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width); -void I422ToABGRRow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, + const struct YuvConstants* yuvconstants, int width); void I422ToRGBARow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); void I422ToRGB24Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width); -void I422ToRAWRow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_raw, - int width); void I422ToARGB4444Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB1555Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width); void I422ToRGB565Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width); -void YToARGBRow_C(const uint8* src_y, - uint8* dst_argb, - int width); void I422ToARGBRow_AVX2(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I444ToARGBRow_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I444ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_SSSE3(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToARGBRow_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_SSSE3(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_SSSE3(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I411ToARGBRow_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I411ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void NV12ToARGBRow_SSSE3(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void NV21ToARGBRow_SSSE3(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, - int width); +void NV12ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void NV12ToRGB565Row_SSSE3(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void NV21ToRGB565Row_SSSE3(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, - int width); +void NV12ToRGB565Row_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_SSSE3(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void UYVYToARGBRow_SSSE3(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void I422ToBGRARow_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width); -void I422ToABGRRow_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, - int width); +void YUY2ToARGBRow_AVX2(const uint8* src_yuy2, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_AVX2(const uint8* src_uyvy, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGBARow_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB4444Row_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I422ToARGB4444Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToARGB1555Row_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I422ToARGB1555Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGB565Row_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -// RGB24/RAW are unaligned. +void I422ToRGB565Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGB24Row_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width); -void I422ToRAWRow_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_raw, - int width); - -void I444ToARGBRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void I422ToARGBRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void I411ToARGBRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void NV12ToARGBRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_uv, - uint8* dst_argb, - int width); -void NV21ToARGBRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, - int width); -void YUY2ToARGBRow_Unaligned_SSSE3(const uint8* src_yuy2, - uint8* dst_argb, - int width); -void UYVYToARGBRow_Unaligned_SSSE3(const uint8* src_uyvy, - uint8* dst_argb, - int width); -void I422ToBGRARow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width); -void I422ToABGRRow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, - int width); -void I422ToRGBARow_Unaligned_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_rgba, - int width); +void I422ToRGB24Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); void I422ToARGBRow_Any_AVX2(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I444ToARGBRow_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I444ToARGBRow_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToARGBRow_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I422AlphaToARGBRow_Any_SSSE3(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I411ToARGBRow_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I411ToARGBRow_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void NV12ToARGBRow_Any_SSSE3(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void NV12ToARGBRow_Any_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void NV21ToARGBRow_Any_SSSE3(const uint8* src_y, const uint8* src_vu, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void NV21ToARGBRow_Any_AVX2(const uint8* src_y, + const uint8* src_vu, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void NV12ToRGB565Row_Any_SSSE3(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void NV21ToRGB565Row_Any_SSSE3(const uint8* src_y, - const uint8* src_vu, - uint8* dst_argb, - int width); +void NV12ToRGB565Row_Any_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void YUY2ToARGBRow_Any_SSSE3(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void UYVYToARGBRow_Any_SSSE3(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void I422ToBGRARow_Any_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width); -void I422ToABGRRow_Any_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, - int width); +void YUY2ToARGBRow_Any_AVX2(const uint8* src_yuy2, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_AVX2(const uint8* src_uyvy, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGBARow_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB4444Row_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); +void I422ToARGB4444Row_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgba, + const struct YuvConstants* yuvconstants, + int width); void I422ToARGB1555Row_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); +void I422ToARGB1555Row_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgba, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGB565Row_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width); -// RGB24/RAW are unaligned. +void I422ToRGB565Row_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgba, + const struct YuvConstants* yuvconstants, + int width); void I422ToRGB24Row_Any_SSSE3(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void I422ToRAWRow_Any_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void YToARGBRow_SSE2(const uint8* src_y, - uint8* dst_argb, - int width); -void YToARGBRow_NEON(const uint8* src_y, - uint8* dst_argb, - int width); -void YToARGBRow_Any_SSE2(const uint8* src_y, - uint8* dst_argb, - int width); -void YToARGBRow_Any_NEON(const uint8* src_y, - uint8* dst_argb, - int width); +void I422ToRGB24Row_Any_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); + +void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_AVX2(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_NEON(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_Any_SSE2(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_Any_AVX2(const uint8* src_y, uint8* dst_argb, int width); +void I400ToARGBRow_Any_NEON(const uint8* src_y, uint8* dst_argb, int width); // ARGB preattenuated alpha blend. void ARGBBlendRow_SSSE3(const uint8* src_argb, const uint8* src_argb1, uint8* dst_argb, int width); -void ARGBBlendRow_SSE2(const uint8* src_argb, const uint8* src_argb1, - uint8* dst_argb, int width); void ARGBBlendRow_NEON(const uint8* src_argb, const uint8* src_argb1, uint8* dst_argb, int width); void ARGBBlendRow_C(const uint8* src_argb, const uint8* src_argb1, uint8* dst_argb, int width); +// Unattenuated planar alpha blend. +void BlendPlaneRow_SSSE3(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width); +void BlendPlaneRow_Any_SSSE3(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width); +void BlendPlaneRow_AVX2(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width); +void BlendPlaneRow_Any_AVX2(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width); +void BlendPlaneRow_C(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width); + // ARGB multiply images. Same API as Blend, but these require // pointer and width alignment for SSE2. void ARGBMultiplyRow_C(const uint8* src_argb, const uint8* src_argb1, @@ -1359,247 +1518,202 @@ void ARGBSubtractRow_NEON(const uint8* src_argb, const uint8* src_argb1, void ARGBSubtractRow_Any_NEON(const uint8* src_argb, const uint8* src_argb1, uint8* dst_argb, int width); -void ARGBToRGB24Row_Any_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRAWRow_Any_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB565Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB1555Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB4444Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGB24Row_Any_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRAWRow_Any_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, + int width); +void ARGBToARGB4444Row_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, + int width); -void ARGBToRGB24Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRAWRow_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToRGB565Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB1555Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); -void ARGBToARGB4444Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int pix); +void ARGBToRGB565DitherRow_Any_SSE2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); +void ARGBToRGB565DitherRow_Any_AVX2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); + +void ARGBToRGB565Row_Any_AVX2(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_Any_AVX2(const uint8* src_argb, uint8* dst_rgb, + int width); +void ARGBToARGB4444Row_Any_AVX2(const uint8* src_argb, uint8* dst_rgb, + int width); + +void ARGBToRGB24Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRAWRow_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToRGB565Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, int width); +void ARGBToARGB1555Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, + int width); +void ARGBToARGB4444Row_Any_NEON(const uint8* src_argb, uint8* dst_rgb, + int width); +void ARGBToRGB565DitherRow_Any_NEON(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width); void I444ToARGBRow_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGBRow_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); +void I422AlphaToARGBRow_Any_NEON(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + const uint8* src_a, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width); void I411ToARGBRow_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, - int width); -void I422ToBGRARow_Any_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void I422ToABGRRow_Any_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToRGBARow_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToRGB24Row_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void I422ToRAWRow_Any_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); void I422ToARGB4444Row_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGB1555Row_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToRGB565Row_Any_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV12ToARGBRow_Any_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV21ToARGBRow_Any_NEON(const uint8* src_y, - const uint8* src_uv, + const uint8* src_vu, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void NV12ToRGB565Row_Any_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, - int width); -void NV21ToRGB565Row_Any_NEON(const uint8* src_y, - const uint8* src_uv, - uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void YUY2ToARGBRow_Any_NEON(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void UYVYToARGBRow_Any_NEON(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGBRow_MIPS_DSPR2(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, - int width); -void I422ToBGRARow_MIPS_DSPR2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void I422ToABGRRow_MIPS_DSPR2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); void I422ToARGBRow_MIPS_DSPR2(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, - int width); -void I422ToBGRARow_MIPS_DSPR2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, - int width); -void I422ToABGRRow_MIPS_DSPR2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width); -void YUY2ToYRow_AVX2(const uint8* src_yuy2, uint8* dst_y, int pix); +void YUY2ToYRow_AVX2(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_AVX2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_AVX2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_SSE2(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_SSE2(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_y, int pix); -void YUY2ToUVRow_Unaligned_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToUV422Row_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_NEON(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_NEON(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_C(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_C(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_C(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_C(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_Any_AVX2(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_Any_AVX2(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_Any_AVX2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_Any_AVX2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_Any_SSE2(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_Any_SSE2(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_Any_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_Any_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void YUY2ToYRow_Any_NEON(const uint8* src_yuy2, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void YUY2ToYRow_Any_NEON(const uint8* src_yuy2, uint8* dst_y, int width); void YUY2ToUVRow_Any_NEON(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void YUY2ToUV422Row_Any_NEON(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_AVX2(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_AVX2(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_AVX2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_AVX2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_SSE2(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_SSE2(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_y, int pix); -void UYVYToUVRow_Unaligned_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToUV422Row_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_AVX2(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_AVX2(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_AVX2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_AVX2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_NEON(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_NEON(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); -void UYVYToYRow_C(const uint8* src_uyvy, uint8* dst_y, int pix); +void UYVYToYRow_C(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_C(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_C(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_Any_AVX2(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_Any_AVX2(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_Any_AVX2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_Any_AVX2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_Any_SSE2(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_Any_SSE2(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_Any_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_Any_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); -void UYVYToYRow_Any_NEON(const uint8* src_uyvy, uint8* dst_y, int pix); + uint8* dst_u, uint8* dst_v, int width); +void UYVYToYRow_Any_NEON(const uint8* src_uyvy, uint8* dst_y, int width); void UYVYToUVRow_Any_NEON(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix); + uint8* dst_u, uint8* dst_v, int width); void UYVYToUV422Row_Any_NEON(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix); - -void HalfRow_C(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix); -void HalfRow_SSE2(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix); -void HalfRow_AVX2(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix); -void HalfRow_NEON(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix); - -void HalfRow_16_C(const uint16* src_uv, int src_uv_stride, - uint16* dst_uv, int pix); - -void ARGBToBayerRow_C(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix); -void ARGBToBayerRow_SSSE3(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix); -void ARGBToBayerRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix); -void ARGBToBayerRow_Any_SSSE3(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix); -void ARGBToBayerRow_Any_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix); -void ARGBToBayerGGRow_C(const uint8* src_argb, uint8* dst_bayer, - uint32 /* selector */, int pix); -void ARGBToBayerGGRow_SSE2(const uint8* src_argb, uint8* dst_bayer, - uint32 /* selector */, int pix); -void ARGBToBayerGGRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 /* selector */, int pix); -void ARGBToBayerGGRow_Any_SSE2(const uint8* src_argb, uint8* dst_bayer, - uint32 /* selector */, int pix); -void ARGBToBayerGGRow_Any_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 /* selector */, int pix); + uint8* dst_u, uint8* dst_v, int width); void I422ToYUY2Row_C(const uint8* src_y, const uint8* src_u, @@ -1644,7 +1758,6 @@ void I422ToUYVYRow_Any_NEON(const uint8* src_y, // Effects related row functions. void ARGBAttenuateRow_C(const uint8* src_argb, uint8* dst_argb, int width); -void ARGBAttenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width); void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width); void ARGBAttenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width); void ARGBAttenuateRow_NEON(const uint8* src_argb, uint8* dst_argb, int width); @@ -1724,9 +1837,6 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, void InterpolateRow_C(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); -void InterpolateRow_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); void InterpolateRow_SSSE3(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); @@ -1736,30 +1846,21 @@ void InterpolateRow_AVX2(uint8* dst_ptr, const uint8* src_ptr, void InterpolateRow_NEON(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); -void InterpolateRows_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); -void InterpolateRow_Unaligned_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); -void InterpolateRow_Unaligned_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); +void InterpolateRow_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride_ptr, int width, + int source_y_fraction); void InterpolateRow_Any_NEON(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); -void InterpolateRow_Any_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); void InterpolateRow_Any_SSSE3(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); void InterpolateRow_Any_AVX2(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride_ptr, int width, int source_y_fraction); -void InterpolateRows_Any_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride_ptr, int width, - int source_y_fraction); +void InterpolateRow_Any_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride_ptr, int width, + int source_y_fraction); void InterpolateRow_16_C(uint16* dst_ptr, const uint16* src_ptr, ptrdiff_t src_stride_ptr, @@ -1796,6 +1897,18 @@ void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width); void SobelXYRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width); +void SobelRow_Any_SSE2(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_argb, int width); +void SobelRow_Any_NEON(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_argb, int width); +void SobelToPlaneRow_Any_SSE2(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_y, int width); +void SobelToPlaneRow_Any_NEON(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_y, int width); +void SobelXYRow_Any_SSE2(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_argb, int width); +void SobelXYRow_Any_NEON(const uint8* src_sobelx, const uint8* src_sobely, + uint8* dst_argb, int width); void ARGBPolynomialRow_C(const uint8* src_argb, uint8* dst_argb, const float* poly, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/scale.h b/TMessagesProj/jni/libyuv/include/libyuv/scale.h index a3bc07e0..102158d1 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/scale.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/scale.h @@ -34,6 +34,7 @@ void ScalePlane(const uint8* src, int src_stride, int dst_width, int dst_height, enum FilterMode filtering); +LIBYUV_API void ScalePlane_16(const uint16* src, int src_stride, int src_width, int src_height, uint16* dst, int dst_stride, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/scale_argb.h b/TMessagesProj/jni/libyuv/include/libyuv/scale_argb.h index 0c9b3625..b56cf520 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/scale_argb.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/scale_argb.h @@ -35,7 +35,6 @@ int ARGBScaleClip(const uint8* src_argb, int src_stride_argb, int clip_x, int clip_y, int clip_width, int clip_height, enum FilterMode filtering); -// TODO(fbarchard): Implement this. // Scale with YUV conversion to ARGB and clipping. LIBYUV_API int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/scale_row.h b/TMessagesProj/jni/libyuv/include/libyuv/scale_row.h index 70e6bc55..45127bda 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/scale_row.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/scale_row.h @@ -12,53 +12,79 @@ #define INCLUDE_LIBYUV_SCALE_ROW_H_ #include "libyuv/basic_types.h" +#include "libyuv/scale.h" #ifdef __cplusplus namespace libyuv { extern "C" { #endif -#if defined(__pnacl__) || defined(__CLR_VER) || defined(COVERAGE_ENABLED) || \ - defined(TARGET_IPHONE_SIMULATOR) +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__i386__) && !defined(__SSE2__)) #define LIBYUV_DISABLE_X86 #endif +// GCC >= 4.7.0 required for AVX2. +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) +#define GCC_HAS_AVX2 1 +#endif // GNUC >= 4.7 +#endif // __GNUC__ + +// clang >= 3.4.0 required for AVX2. +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) +#define CLANG_HAS_AVX2 1 +#endif // clang >= 3.4 +#endif // __clang__ + +// Visual C 2012 required for AVX2. +#if defined(_M_IX86) && !defined(__clang__) && \ + defined(_MSC_VER) && _MSC_VER >= 1700 +#define VISUALC_HAS_AVX2 1 +#endif // VisualStudio >= 2012 + // The following are available on all x86 platforms: #if !defined(LIBYUV_DISABLE_X86) && \ (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -#define HAS_SCALEROWDOWN2_SSE2 -#define HAS_SCALEROWDOWN4_SSE2 -#define HAS_SCALEROWDOWN34_SSSE3 -#define HAS_SCALEROWDOWN38_SSSE3 -#define HAS_SCALEADDROWS_SSE2 -#define HAS_SCALEFILTERCOLS_SSSE3 -#define HAS_SCALECOLSUP2_SSE2 +#define HAS_FIXEDDIV1_X86 +#define HAS_FIXEDDIV_X86 +#define HAS_SCALEARGBCOLS_SSE2 +#define HAS_SCALEARGBCOLSUP2_SSE2 +#define HAS_SCALEARGBFILTERCOLS_SSSE3 #define HAS_SCALEARGBROWDOWN2_SSE2 #define HAS_SCALEARGBROWDOWNEVEN_SSE2 -#define HAS_SCALEARGBCOLS_SSE2 -#define HAS_SCALEARGBFILTERCOLS_SSSE3 -#define HAS_SCALEARGBCOLSUP2_SSE2 -#define HAS_FIXEDDIV_X86 -#define HAS_FIXEDDIV1_X86 +#define HAS_SCALECOLSUP2_SSE2 +#define HAS_SCALEFILTERCOLS_SSSE3 +#define HAS_SCALEROWDOWN2_SSSE3 +#define HAS_SCALEROWDOWN34_SSSE3 +#define HAS_SCALEROWDOWN38_SSSE3 +#define HAS_SCALEROWDOWN4_SSSE3 +#define HAS_SCALEADDROW_SSE2 +#endif + +// The following are available on all x86 platforms, but +// require VS2012, clang 3.4 or gcc 4.7. +// The code supports NaCL but requires a new compiler and validator. +#if !defined(LIBYUV_DISABLE_X86) && (defined(VISUALC_HAS_AVX2) || \ + defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) +#define HAS_SCALEADDROW_AVX2 +#define HAS_SCALEROWDOWN2_AVX2 +#define HAS_SCALEROWDOWN4_AVX2 #endif // The following are available on Neon platforms: #if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) -#define HAS_SCALEROWDOWN2_NEON -#define HAS_SCALEROWDOWN4_NEON -#define HAS_SCALEROWDOWN34_NEON -#define HAS_SCALEROWDOWN38_NEON -#define HAS_SCALEARGBROWDOWNEVEN_NEON -#define HAS_SCALEARGBROWDOWN2_NEON -#elif !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ - (defined(__aarch64__) || defined(LIBYUV_NEON)) -#define HAS_SCALEROWDOWN2_NEON -#define HAS_SCALEROWDOWN4_NEON -#define HAS_SCALEROWDOWN34_NEON -#define HAS_SCALEROWDOWN38_NEON + (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) +#define HAS_SCALEARGBCOLS_NEON #define HAS_SCALEARGBROWDOWN2_NEON #define HAS_SCALEARGBROWDOWNEVEN_NEON +#define HAS_SCALEFILTERCOLS_NEON +#define HAS_SCALEROWDOWN2_NEON +#define HAS_SCALEROWDOWN34_NEON +#define HAS_SCALEROWDOWN38_NEON +#define HAS_SCALEROWDOWN4_NEON +#define HAS_SCALEARGBFILTERCOLS_NEON #endif // The following are available on Mips platforms: @@ -172,10 +198,8 @@ void ScaleRowDown38_2_Box_C(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); void ScaleRowDown38_2_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride, uint16* dst_ptr, int dst_width); -void ScaleAddRows_C(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, int src_height); -void ScaleAddRows_16_C(const uint16* src_ptr, ptrdiff_t src_stride, - uint32* dst_ptr, int src_width, int src_height); +void ScaleAddRow_C(const uint8* src_ptr, uint16* dst_ptr, int src_width); +void ScaleAddRow_16_C(const uint16* src_ptr, uint32* dst_ptr, int src_width); void ScaleARGBRowDown2_C(const uint8* src_argb, ptrdiff_t src_stride, uint8* dst_argb, int dst_width); @@ -202,25 +226,28 @@ void ScaleARGBFilterCols_C(uint8* dst_argb, const uint8* src_argb, void ScaleARGBFilterCols64_C(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx); -void ScaleRowDown2_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +// Specialized scalers for x86. +void ScaleRowDown2_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Linear_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); -void ScaleRowDown2Linear_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +void ScaleRowDown2Linear_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); -void ScaleRowDown2Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +void ScaleRowDown2Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); -void ScaleRowDown2_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width); -void ScaleRowDown2Linear_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width); -void ScaleRowDown2Box_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width); -void ScaleRowDown4_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +void ScaleRowDown4_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); -void ScaleRowDown4Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +void ScaleRowDown4Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); + void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, @@ -237,46 +264,124 @@ void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); -void ScaleAddRows_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, - int src_height); +void ScaleRowDown2_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Linear_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Box_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Linear_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown2Box_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4Box_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4Box_Any_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); + +void ScaleRowDown34_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown34_1_Box_Any_SSSE3(const uint8* src_ptr, + ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown34_0_Box_Any_SSSE3(const uint8* src_ptr, + ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown38_Any_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown38_3_Box_Any_SSSE3(const uint8* src_ptr, + ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown38_2_Box_Any_SSSE3(const uint8* src_ptr, + ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); + +void ScaleAddRow_SSE2(const uint8* src_ptr, uint16* dst_ptr, int src_width); +void ScaleAddRow_AVX2(const uint8* src_ptr, uint16* dst_ptr, int src_width); +void ScaleAddRow_Any_SSE2(const uint8* src_ptr, uint16* dst_ptr, int src_width); +void ScaleAddRow_Any_AVX2(const uint8* src_ptr, uint16* dst_ptr, int src_width); + void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, int dst_width, int x, int dx); void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr, int dst_width, int x, int dx); -void ScaleARGBRowDown2_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width); -void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width); -void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width); -void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, - int src_stepx, - uint8* dst_argb, int dst_width); -void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - int src_stepx, - uint8* dst_argb, int dst_width); + + +// ARGB Column functions void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx); void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx); void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx); -// Row functions. +void ScaleARGBFilterCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx); +void ScaleARGBCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx); +void ScaleARGBFilterCols_Any_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx); +void ScaleARGBCols_Any_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx); + +// ARGB Row functions +void ScaleARGBRowDown2_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleARGBRowDown2_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Linear_Any_SSE2(const uint8* src_argb, + ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Box_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleARGBRowDown2Linear_Any_NEON(const uint8* src_argb, + ptrdiff_t src_stride, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDown2Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); + +void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, uint8* dst_argb, int dst_width); +void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, uint8* dst_argb, int dst_width); void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, uint8* dst_argb, int dst_width); -void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst, int dst_width); -void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst, int dst_width); +void ScaleARGBRowDownEven_Any_SSE2(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDownEvenBox_Any_SSE2(const uint8* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDownEven_Any_NEON(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); +void ScaleARGBRowDownEvenBox_Any_NEON(const uint8* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); // ScaleRowDown2Box also used by planar functions // NEON downscalers with interpolation. @@ -284,7 +389,8 @@ void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, // Note - not static due to reuse in convert for 444 to 420. void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width); - +void ScaleRowDown2Linear_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width); @@ -319,6 +425,42 @@ void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width); +void ScaleRowDown2_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleRowDown2Linear_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleRowDown2Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width); +void ScaleRowDown4_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown4Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown34_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown34_0_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +void ScaleRowDown34_1_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +// 32 -> 12 +void ScaleRowDown38_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +// 32x3 -> 12x1 +void ScaleRowDown38_3_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); +// 32x2 -> 12x1 +void ScaleRowDown38_2_Box_Any_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width); + +void ScaleAddRow_NEON(const uint8* src_ptr, uint16* dst_ptr, int src_width); +void ScaleAddRow_Any_NEON(const uint8* src_ptr, uint16* dst_ptr, int src_width); + +void ScaleFilterCols_NEON(uint8* dst_ptr, const uint8* src_ptr, + int dst_width, int x, int dx); + +void ScaleFilterCols_Any_NEON(uint8* dst_ptr, const uint8* src_ptr, + int dst_width, int x, int dx); + + void ScaleRowDown2_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width); void ScaleRowDown2Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, diff --git a/TMessagesProj/jni/libyuv/include/libyuv/version.h b/TMessagesProj/jni/libyuv/include/libyuv/version.h index c6952040..ab0f88d9 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/version.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1074 +#define LIBYUV_VERSION 1561 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/TMessagesProj/jni/libyuv/include/libyuv/video_common.h b/TMessagesProj/jni/libyuv/include/libyuv/video_common.h index 91acc2ff..ad934e42 100644 --- a/TMessagesProj/jni/libyuv/include/libyuv/video_common.h +++ b/TMessagesProj/jni/libyuv/include/libyuv/video_common.h @@ -62,7 +62,7 @@ enum FourCC { // 2 Secondary YUV formats: row biplanar. FOURCC_M420 = FOURCC('M', '4', '2', '0'), - FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), + FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), // deprecated. // 9 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp. FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), @@ -75,7 +75,7 @@ enum FourCC { FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE. FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE. - // 4 Secondary RGB formats: 4 Bayer Patterns. + // 4 Secondary RGB formats: 4 Bayer Patterns. deprecated. FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'), FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'), FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'), @@ -90,7 +90,8 @@ enum FourCC { FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. FOURCC_J420 = FOURCC('J', '4', '2', '0'), - FOURCC_J400 = FOURCC('J', '4', '0', '0'), + FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc + FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc // 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc. FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420. @@ -150,6 +151,7 @@ enum FourCCBpp { FOURCC_BPP_YU12 = 12, FOURCC_BPP_J420 = 12, FOURCC_BPP_J400 = 8, + FOURCC_BPP_H420 = 12, FOURCC_BPP_MJPG = 0, // 0 means unknown. FOURCC_BPP_H264 = 0, FOURCC_BPP_IYUV = 12, diff --git a/TMessagesProj/jni/libyuv/source/compare.cc b/TMessagesProj/jni/libyuv/source/compare.cc index dc715e01..e3846bdf 100644 --- a/TMessagesProj/jni/libyuv/source/compare.cc +++ b/TMessagesProj/jni/libyuv/source/compare.cc @@ -17,38 +17,23 @@ #endif #include "libyuv/basic_types.h" +#include "libyuv/compare_row.h" #include "libyuv/cpu_id.h" #include "libyuv/row.h" +#include "libyuv/video_common.h" #ifdef __cplusplus namespace libyuv { extern "C" { #endif -// hash seed of 5381 recommended. -// Internal C version of HashDjb2 with int sized count for efficiency. -uint32 HashDjb2_C(const uint8* src, int count, uint32 seed); - -// This module is for Visual C x86 -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || \ - (defined(__x86_64__) || (defined(__i386__) && !defined(__pic__)))) -#define HAS_HASHDJB2_SSE41 -uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed); - -#if _MSC_VER >= 1700 -#define HAS_HASHDJB2_AVX2 -uint32 HashDjb2_AVX2(const uint8* src, int count, uint32 seed); -#endif - -#endif // HAS_HASHDJB2_SSE41 - // hash seed of 5381 recommended. LIBYUV_API uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed) { const int kBlockSize = 1 << 15; // 32768; int remainder; - uint32 (*HashDjb2_SSE)(const uint8* src, int count, uint32 seed) = HashDjb2_C; + uint32 (*HashDjb2_SSE)(const uint8* src, int count, uint32 seed) = + HashDjb2_C; #if defined(HAS_HASHDJB2_SSE41) if (TestCpuFlag(kCpuHasSSE41)) { HashDjb2_SSE = HashDjb2_SSE41; @@ -78,22 +63,53 @@ uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed) { return seed; } -uint32 SumSquareError_C(const uint8* src_a, const uint8* src_b, int count); -#if !defined(LIBYUV_DISABLE_NEON) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) -#define HAS_SUMSQUAREERROR_NEON -uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count); -#endif -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -#define HAS_SUMSQUAREERROR_SSE2 -uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count); -#endif -// Visual C 2012 required for AVX2. -#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && _MSC_VER >= 1700 -#define HAS_SUMSQUAREERROR_AVX2 -uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count); -#endif +static uint32 ARGBDetectRow_C(const uint8* argb, int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + if (argb[0] != 255) { // First byte is not Alpha of 255, so not ARGB. + return FOURCC_BGRA; + } + if (argb[3] != 255) { // 4th byte is not Alpha of 255, so not BGRA. + return FOURCC_ARGB; + } + if (argb[4] != 255) { // Second pixel first byte is not Alpha of 255. + return FOURCC_BGRA; + } + if (argb[7] != 255) { // Second pixel 4th byte is not Alpha of 255. + return FOURCC_ARGB; + } + argb += 8; + } + if (width & 1) { + if (argb[0] != 255) { // First byte is not Alpha of 255, so not ARGB. + return FOURCC_BGRA; + } + if (argb[3] != 255) { // 4th byte is not Alpha of 255, so not BGRA. + return FOURCC_ARGB; + } + } + return 0; +} + +// Scan an opaque argb image and return fourcc based on alpha offset. +// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. +LIBYUV_API +uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height) { + uint32 fourcc = 0; + int h; + + // Coalesce rows. + if (stride_argb == width * 4) { + width *= height; + height = 1; + stride_argb = 0; + } + for (h = 0; h < height && fourcc == 0; ++h) { + fourcc = ARGBDetectRow_C(argb, width); + argb += stride_argb; + } + return fourcc; +} // TODO(fbarchard): Refactor into row function. LIBYUV_API @@ -114,8 +130,7 @@ uint64 ComputeSumSquareError(const uint8* src_a, const uint8* src_b, } #endif #if defined(HAS_SUMSQUAREERROR_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(src_a, 16) && IS_ALIGNED(src_b, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { // Note only used for multiples of 16 so count is not checked. SumSquareError = SumSquareError_SSE2; } diff --git a/TMessagesProj/jni/libyuv/source/compare_common.cc b/TMessagesProj/jni/libyuv/source/compare_common.cc index c546b518..42fc5893 100644 --- a/TMessagesProj/jni/libyuv/source/compare_common.cc +++ b/TMessagesProj/jni/libyuv/source/compare_common.cc @@ -10,6 +10,8 @@ #include "libyuv/basic_types.h" +#include "libyuv/compare_row.h" + #ifdef __cplusplus namespace libyuv { extern "C" { diff --git a/TMessagesProj/jni/libyuv/source/compare_neon.cc b/TMessagesProj/jni/libyuv/source/compare_neon.cc index 55052c0e..49aa3b4e 100644 --- a/TMessagesProj/jni/libyuv/source/compare_neon.cc +++ b/TMessagesProj/jni/libyuv/source/compare_neon.cc @@ -9,6 +9,8 @@ */ #include "libyuv/basic_types.h" + +#include "libyuv/compare_row.h" #include "libyuv/row.h" #ifdef __cplusplus @@ -16,7 +18,8 @@ namespace libyuv { extern "C" { #endif -#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) +#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \ + !defined(__aarch64__) uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count) { volatile uint32 sse; @@ -26,7 +29,6 @@ uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count) { "vmov.u8 q9, #0 \n" "vmov.u8 q11, #0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" @@ -56,46 +58,7 @@ uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count) { return sse; } -#elif !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) - -uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count) { - volatile uint32 sse; - asm volatile ( - "eor v16.16b, v16.16b, v16.16b \n" - "eor v18.16b, v18.16b, v18.16b \n" - "eor v17.16b, v17.16b, v17.16b \n" - "eor v19.16b, v19.16b, v19.16b \n" - - ".p2align 2 \n" - "1: \n" - MEMACCESS(0) - "ld1 {v0.16b}, [%0], #16 \n" - MEMACCESS(1) - "ld1 {v1.16b}, [%1], #16 \n" - "subs %2, %2, #16 \n" - "usubl v2.8h, v0.8b, v1.8b \n" - "usubl2 v3.8h, v0.16b, v1.16b \n" - "smlal v16.4s, v2.4h, v2.4h \n" - "smlal v17.4s, v3.4h, v3.4h \n" - "smlal2 v18.4s, v2.8h, v2.8h \n" - "smlal2 v19.4s, v3.8h, v3.8h \n" - "bgt 1b \n" - - "add v16.4s, v16.4s, v17.4s \n" - "add v18.4s, v18.4s, v19.4s \n" - "add v19.4s, v16.4s, v18.4s \n" - "addv s0, v19.4s \n" - "fmov %w3, s0 \n" - : "+r"(src_a), - "+r"(src_b), - "+r"(count), - "=r"(sse) - : - : "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19"); - return sse; -} - -#endif // __ARM_NEON__ +#endif // defined(__ARM_NEON__) && !defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/compare_posix.cc b/TMessagesProj/jni/libyuv/source/compare_posix.cc deleted file mode 100644 index ac361190..00000000 --- a/TMessagesProj/jni/libyuv/source/compare_posix.cc +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2012 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "libyuv/basic_types.h" -#include "libyuv/row.h" - -#ifdef __cplusplus -namespace libyuv { -extern "C" { -#endif - -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count) { - uint32 sse; - asm volatile ( // NOLINT - "pxor %%xmm0,%%xmm0 \n" - "pxor %%xmm5,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm1 \n" - "lea " MEMLEA(0x10, 0) ",%0 \n" - "movdqa " MEMACCESS(1) ",%%xmm2 \n" - "lea " MEMLEA(0x10, 1) ",%1 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psubusb %%xmm2,%%xmm1 \n" - "psubusb %%xmm3,%%xmm2 \n" - "por %%xmm2,%%xmm1 \n" - "movdqa %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm1 \n" - "punpckhbw %%xmm5,%%xmm2 \n" - "pmaddwd %%xmm1,%%xmm1 \n" - "pmaddwd %%xmm2,%%xmm2 \n" - "paddd %%xmm1,%%xmm0 \n" - "paddd %%xmm2,%%xmm0 \n" - "jg 1b \n" - - "pshufd $0xee,%%xmm0,%%xmm1 \n" - "paddd %%xmm1,%%xmm0 \n" - "pshufd $0x1,%%xmm0,%%xmm1 \n" - "paddd %%xmm1,%%xmm0 \n" - "movd %%xmm0,%3 \n" - - : "+r"(src_a), // %0 - "+r"(src_b), // %1 - "+r"(count), // %2 - "=g"(sse) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); // NOLINT - return sse; -} - -#endif // defined(__x86_64__) || defined(__i386__) - -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(__x86_64__) || (defined(__i386__) && !defined(__pic__))) -#define HAS_HASHDJB2_SSE41 -static uvec32 kHash16x33 = { 0x92d9e201, 0, 0, 0 }; // 33 ^ 16 -static uvec32 kHashMul0 = { - 0x0c3525e1, // 33 ^ 15 - 0xa3476dc1, // 33 ^ 14 - 0x3b4039a1, // 33 ^ 13 - 0x4f5f0981, // 33 ^ 12 -}; -static uvec32 kHashMul1 = { - 0x30f35d61, // 33 ^ 11 - 0x855cb541, // 33 ^ 10 - 0x040a9121, // 33 ^ 9 - 0x747c7101, // 33 ^ 8 -}; -static uvec32 kHashMul2 = { - 0xec41d4e1, // 33 ^ 7 - 0x4cfa3cc1, // 33 ^ 6 - 0x025528a1, // 33 ^ 5 - 0x00121881, // 33 ^ 4 -}; -static uvec32 kHashMul3 = { - 0x00008c61, // 33 ^ 3 - 0x00000441, // 33 ^ 2 - 0x00000021, // 33 ^ 1 - 0x00000001, // 33 ^ 0 -}; - -uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed) { - uint32 hash; - asm volatile ( // NOLINT - "movd %2,%%xmm0 \n" - "pxor %%xmm7,%%xmm7 \n" - "movdqa %4,%%xmm6 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm1 \n" - "lea " MEMLEA(0x10, 0) ",%0 \n" - "pmulld %%xmm6,%%xmm0 \n" - "movdqa %5,%%xmm5 \n" - "movdqa %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm7,%%xmm2 \n" - "movdqa %%xmm2,%%xmm3 \n" - "punpcklwd %%xmm7,%%xmm3 \n" - "pmulld %%xmm5,%%xmm3 \n" - "movdqa %6,%%xmm5 \n" - "movdqa %%xmm2,%%xmm4 \n" - "punpckhwd %%xmm7,%%xmm4 \n" - "pmulld %%xmm5,%%xmm4 \n" - "movdqa %7,%%xmm5 \n" - "punpckhbw %%xmm7,%%xmm1 \n" - "movdqa %%xmm1,%%xmm2 \n" - "punpcklwd %%xmm7,%%xmm2 \n" - "pmulld %%xmm5,%%xmm2 \n" - "movdqa %8,%%xmm5 \n" - "punpckhwd %%xmm7,%%xmm1 \n" - "pmulld %%xmm5,%%xmm1 \n" - "paddd %%xmm4,%%xmm3 \n" - "paddd %%xmm2,%%xmm1 \n" - "sub $0x10,%1 \n" - "paddd %%xmm3,%%xmm1 \n" - "pshufd $0xe,%%xmm1,%%xmm2 \n" - "paddd %%xmm2,%%xmm1 \n" - "pshufd $0x1,%%xmm1,%%xmm2 \n" - "paddd %%xmm2,%%xmm1 \n" - "paddd %%xmm1,%%xmm0 \n" - "jg 1b \n" - "movd %%xmm0,%3 \n" - : "+r"(src), // %0 - "+r"(count), // %1 - "+rm"(seed), // %2 - "=g"(hash) // %3 - : "m"(kHash16x33), // %4 - "m"(kHashMul0), // %5 - "m"(kHashMul1), // %6 - "m"(kHashMul2), // %7 - "m"(kHashMul3) // %8 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); // NOLINT - return hash; -} -#endif // defined(__x86_64__) || (defined(__i386__) && !defined(__pic__))) - -#ifdef __cplusplus -} // extern "C" -} // namespace libyuv -#endif - diff --git a/TMessagesProj/jni/libyuv/source/compare_win.cc b/TMessagesProj/jni/libyuv/source/compare_win.cc index 99831651..dc86fe25 100644 --- a/TMessagesProj/jni/libyuv/source/compare_win.cc +++ b/TMessagesProj/jni/libyuv/source/compare_win.cc @@ -9,6 +9,8 @@ */ #include "libyuv/basic_types.h" + +#include "libyuv/compare_row.h" #include "libyuv/row.h" #ifdef __cplusplus @@ -16,9 +18,10 @@ namespace libyuv { extern "C" { #endif -#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) +// This module is for 32 bit Visual C x86 and clangcl +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) -__declspec(naked) __declspec(align(16)) +__declspec(naked) uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count) { __asm { mov eax, [esp + 4] // src_a @@ -27,13 +30,11 @@ uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count) { pxor xmm0, xmm0 pxor xmm5, xmm5 - align 4 wloop: - movdqa xmm1, [eax] + movdqu xmm1, [eax] lea eax, [eax + 16] - movdqa xmm2, [edx] + movdqu xmm2, [edx] lea edx, [edx + 16] - sub ecx, 16 movdqa xmm3, xmm1 // abs trick psubusb xmm1, xmm2 psubusb xmm2, xmm3 @@ -45,6 +46,7 @@ uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count) { pmaddwd xmm2, xmm2 paddd xmm0, xmm1 paddd xmm0, xmm2 + sub ecx, 16 jg wloop pshufd xmm1, xmm0, 0xee @@ -60,7 +62,7 @@ uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count) { #if _MSC_VER >= 1700 // C4752: found Intel(R) Advanced Vector Extensions; consider using /arch:AVX. #pragma warning(disable: 4752) -__declspec(naked) __declspec(align(16)) +__declspec(naked) uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count) { __asm { mov eax, [esp + 4] // src_a @@ -70,12 +72,10 @@ uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count) { vpxor ymm5, ymm5, ymm5 // constant 0 for unpck sub edx, eax - align 4 wloop: vmovdqu ymm1, [eax] vmovdqu ymm2, [eax + edx] lea eax, [eax + 32] - sub ecx, 32 vpsubusb ymm3, ymm1, ymm2 // abs difference trick vpsubusb ymm2, ymm2, ymm1 vpor ymm1, ymm2, ymm3 @@ -85,6 +85,7 @@ uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count) { vpmaddwd ymm1, ymm1, ymm1 vpaddd ymm0, ymm0, ymm1 vpaddd ymm0, ymm0, ymm2 + sub ecx, 32 jg wloop vpshufd ymm1, ymm0, 0xee // 3, 2 + 1, 0 both lanes. @@ -100,42 +101,33 @@ uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count) { } #endif // _MSC_VER >= 1700 -#define HAS_HASHDJB2_SSE41 -static uvec32 kHash16x33 = { 0x92d9e201, 0, 0, 0 }; // 33 ^ 16 -static uvec32 kHashMul0 = { +uvec32 kHash16x33 = { 0x92d9e201, 0, 0, 0 }; // 33 ^ 16 +uvec32 kHashMul0 = { 0x0c3525e1, // 33 ^ 15 0xa3476dc1, // 33 ^ 14 0x3b4039a1, // 33 ^ 13 0x4f5f0981, // 33 ^ 12 }; -static uvec32 kHashMul1 = { +uvec32 kHashMul1 = { 0x30f35d61, // 33 ^ 11 0x855cb541, // 33 ^ 10 0x040a9121, // 33 ^ 9 0x747c7101, // 33 ^ 8 }; -static uvec32 kHashMul2 = { +uvec32 kHashMul2 = { 0xec41d4e1, // 33 ^ 7 0x4cfa3cc1, // 33 ^ 6 0x025528a1, // 33 ^ 5 0x00121881, // 33 ^ 4 }; -static uvec32 kHashMul3 = { +uvec32 kHashMul3 = { 0x00008c61, // 33 ^ 3 0x00000441, // 33 ^ 2 0x00000021, // 33 ^ 1 0x00000001, // 33 ^ 0 }; -// 27: 66 0F 38 40 C6 pmulld xmm0,xmm6 -// 44: 66 0F 38 40 DD pmulld xmm3,xmm5 -// 59: 66 0F 38 40 E5 pmulld xmm4,xmm5 -// 72: 66 0F 38 40 D5 pmulld xmm2,xmm5 -// 83: 66 0F 38 40 CD pmulld xmm1,xmm5 -#define pmulld(reg) _asm _emit 0x66 _asm _emit 0x0F _asm _emit 0x38 \ - _asm _emit 0x40 _asm _emit reg - -__declspec(naked) __declspec(align(16)) +__declspec(naked) uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed) { __asm { mov eax, [esp + 4] // src @@ -143,34 +135,32 @@ uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed) { movd xmm0, [esp + 12] // seed pxor xmm7, xmm7 // constant 0 for unpck - movdqa xmm6, kHash16x33 + movdqa xmm6, xmmword ptr kHash16x33 - align 4 wloop: movdqu xmm1, [eax] // src[0-15] lea eax, [eax + 16] - pmulld(0xc6) // pmulld xmm0,xmm6 hash *= 33 ^ 16 - movdqa xmm5, kHashMul0 + pmulld xmm0, xmm6 // hash *= 33 ^ 16 + movdqa xmm5, xmmword ptr kHashMul0 movdqa xmm2, xmm1 punpcklbw xmm2, xmm7 // src[0-7] movdqa xmm3, xmm2 punpcklwd xmm3, xmm7 // src[0-3] - pmulld(0xdd) // pmulld xmm3, xmm5 - movdqa xmm5, kHashMul1 + pmulld xmm3, xmm5 + movdqa xmm5, xmmword ptr kHashMul1 movdqa xmm4, xmm2 punpckhwd xmm4, xmm7 // src[4-7] - pmulld(0xe5) // pmulld xmm4, xmm5 - movdqa xmm5, kHashMul2 + pmulld xmm4, xmm5 + movdqa xmm5, xmmword ptr kHashMul2 punpckhbw xmm1, xmm7 // src[8-15] movdqa xmm2, xmm1 punpcklwd xmm2, xmm7 // src[8-11] - pmulld(0xd5) // pmulld xmm2, xmm5 - movdqa xmm5, kHashMul3 + pmulld xmm2, xmm5 + movdqa xmm5, xmmword ptr kHashMul3 punpckhwd xmm1, xmm7 // src[12-15] - pmulld(0xcd) // pmulld xmm1, xmm5 + pmulld xmm1, xmm5 paddd xmm3, xmm4 // add 16 results paddd xmm1, xmm2 - sub ecx, 16 paddd xmm1, xmm3 pshufd xmm2, xmm1, 0x0e // upper 2 dwords @@ -178,6 +168,7 @@ uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed) { pshufd xmm2, xmm1, 0x01 paddd xmm1, xmm2 paddd xmm0, xmm1 + sub ecx, 16 jg wloop movd eax, xmm0 // return hash @@ -187,44 +178,43 @@ uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed) { // Visual C 2012 required for AVX2. #if _MSC_VER >= 1700 -__declspec(naked) __declspec(align(16)) +__declspec(naked) uint32 HashDjb2_AVX2(const uint8* src, int count, uint32 seed) { __asm { mov eax, [esp + 4] // src mov ecx, [esp + 8] // count - movd xmm0, [esp + 12] // seed - movdqa xmm6, kHash16x33 + vmovd xmm0, [esp + 12] // seed - align 4 wloop: - vpmovzxbd xmm3, dword ptr [eax] // src[0-3] - pmulld xmm0, xmm6 // hash *= 33 ^ 16 - vpmovzxbd xmm4, dword ptr [eax + 4] // src[4-7] - pmulld xmm3, kHashMul0 - vpmovzxbd xmm2, dword ptr [eax + 8] // src[8-11] - pmulld xmm4, kHashMul1 - vpmovzxbd xmm1, dword ptr [eax + 12] // src[12-15] - pmulld xmm2, kHashMul2 + vpmovzxbd xmm3, [eax] // src[0-3] + vpmulld xmm0, xmm0, xmmword ptr kHash16x33 // hash *= 33 ^ 16 + vpmovzxbd xmm4, [eax + 4] // src[4-7] + vpmulld xmm3, xmm3, xmmword ptr kHashMul0 + vpmovzxbd xmm2, [eax + 8] // src[8-11] + vpmulld xmm4, xmm4, xmmword ptr kHashMul1 + vpmovzxbd xmm1, [eax + 12] // src[12-15] + vpmulld xmm2, xmm2, xmmword ptr kHashMul2 lea eax, [eax + 16] - pmulld xmm1, kHashMul3 - paddd xmm3, xmm4 // add 16 results - paddd xmm1, xmm2 + vpmulld xmm1, xmm1, xmmword ptr kHashMul3 + vpaddd xmm3, xmm3, xmm4 // add 16 results + vpaddd xmm1, xmm1, xmm2 + vpaddd xmm1, xmm1, xmm3 + vpshufd xmm2, xmm1, 0x0e // upper 2 dwords + vpaddd xmm1, xmm1,xmm2 + vpshufd xmm2, xmm1, 0x01 + vpaddd xmm1, xmm1, xmm2 + vpaddd xmm0, xmm0, xmm1 sub ecx, 16 - paddd xmm1, xmm3 - pshufd xmm2, xmm1, 0x0e // upper 2 dwords - paddd xmm1, xmm2 - pshufd xmm2, xmm1, 0x01 - paddd xmm1, xmm2 - paddd xmm0, xmm1 jg wloop - movd eax, xmm0 // return hash + vmovd eax, xmm0 // return hash + vzeroupper ret } } #endif // _MSC_VER >= 1700 -#endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) +#endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/convert.cc b/TMessagesProj/jni/libyuv/source/convert.cc index c31ecf26..5dc279f8 100644 --- a/TMessagesProj/jni/libyuv/source/convert.cc +++ b/TMessagesProj/jni/libyuv/source/convert.cc @@ -188,17 +188,14 @@ static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1, int width, int height) { int y; void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; -#if defined(HAS_COPYROW_X86) - if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { - CopyRow = CopyRow_X86; +#if defined(HAS_COPYROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; } #endif -#if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && - IS_ALIGNED(src, 16) && - IS_ALIGNED(src_stride_0, 16) && IS_ALIGNED(src_stride_1, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - CopyRow = CopyRow_SSE2; +#if defined(HAS_COPYROW_AVX) + if (TestCpuFlag(kCpuHasAVX)) { + CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX; } #endif #if defined(HAS_COPYROW_ERMS) @@ -207,8 +204,8 @@ static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1, } #endif #if defined(HAS_COPYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { - CopyRow = CopyRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON; } #endif #if defined(HAS_COPYROW_MIPS) @@ -248,8 +245,8 @@ static int X420ToI420(const uint8* src_y, int y; int halfwidth = (width + 1) >> 1; int halfheight = (height + 1) >> 1; - void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) = - SplitUVRow_C; + void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width) = SplitUVRow_C; if (!src_y || !src_uv || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { @@ -283,20 +280,15 @@ static int X420ToI420(const uint8* src_y, src_stride_uv = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_SPLITUVROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { SplitUVRow = SplitUVRow_Any_SSE2; if (IS_ALIGNED(halfwidth, 16)) { - SplitUVRow = SplitUVRow_Unaligned_SSE2; - if (IS_ALIGNED(src_uv, 16) && IS_ALIGNED(src_stride_uv, 16) && - IS_ALIGNED(dst_u, 16) && IS_ALIGNED(dst_stride_u, 16) && - IS_ALIGNED(dst_v, 16) && IS_ALIGNED(dst_stride_v, 16)) { - SplitUVRow = SplitUVRow_SSE2; - } + SplitUVRow = SplitUVRow_SSE2; } } #endif #if defined(HAS_SPLITUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { SplitUVRow = SplitUVRow_Any_AVX2; if (IS_ALIGNED(halfwidth, 32)) { SplitUVRow = SplitUVRow_AVX2; @@ -304,7 +296,7 @@ static int X420ToI420(const uint8* src_y, } #endif #if defined(HAS_SPLITUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { SplitUVRow = SplitUVRow_Any_NEON; if (IS_ALIGNED(halfwidth, 16)) { SplitUVRow = SplitUVRow_NEON; @@ -312,15 +304,13 @@ static int X420ToI420(const uint8* src_y, } #endif #if defined(HAS_SPLITUVROW_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && + IS_ALIGNED(src_uv, 4) && IS_ALIGNED(src_stride_uv, 4) && + IS_ALIGNED(dst_u, 4) && IS_ALIGNED(dst_stride_u, 4) && + IS_ALIGNED(dst_v, 4) && IS_ALIGNED(dst_stride_v, 4)) { SplitUVRow = SplitUVRow_Any_MIPS_DSPR2; if (IS_ALIGNED(halfwidth, 16)) { - SplitUVRow = SplitUVRow_Unaligned_MIPS_DSPR2; - if (IS_ALIGNED(src_uv, 4) && IS_ALIGNED(src_stride_uv, 4) && - IS_ALIGNED(dst_u, 4) && IS_ALIGNED(dst_stride_u, 4) && - IS_ALIGNED(dst_v, 4) && IS_ALIGNED(dst_stride_v, 4)) { - SplitUVRow = SplitUVRow_MIPS_DSPR2; - } + SplitUVRow = SplitUVRow_MIPS_DSPR2; } } #endif @@ -391,125 +381,6 @@ int M420ToI420(const uint8* src_m420, int src_stride_m420, width, height); } -// Convert Q420 to I420. -// Format is rows of YY/YUYV -LIBYUV_API -int Q420ToI420(const uint8* src_y, int src_stride_y, - const uint8* src_yuy2, int src_stride_yuy2, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height) { - int y; - int halfheight; - void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; - void (*YUY2ToUV422Row)(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v, - int pix) = YUY2ToUV422Row_C; - void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) = - YUY2ToYRow_C; - if (!src_y || !src_yuy2 || - !dst_y || !dst_u || !dst_v || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - halfheight = (height + 1) >> 1; - dst_y = dst_y + (height - 1) * dst_stride_y; - dst_u = dst_u + (halfheight - 1) * dst_stride_u; - dst_v = dst_v + (halfheight - 1) * dst_stride_v; - dst_stride_y = -dst_stride_y; - dst_stride_u = -dst_stride_u; - dst_stride_v = -dst_stride_v; - } - // CopyRow for rows of just Y in Q420 copied to Y plane of I420. -#if defined(HAS_COPYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { - CopyRow = CopyRow_NEON; - } -#endif -#if defined(HAS_COPYROW_X86) - if (IS_ALIGNED(width, 4)) { - CopyRow = CopyRow_X86; - } -#endif -#if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && - IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - CopyRow = CopyRow_SSE2; - } -#endif -#if defined(HAS_COPYROW_ERMS) - if (TestCpuFlag(kCpuHasERMS)) { - CopyRow = CopyRow_ERMS; - } -#endif -#if defined(HAS_COPYROW_MIPS) - if (TestCpuFlag(kCpuHasMIPS)) { - CopyRow = CopyRow_MIPS; - } -#endif - -#if defined(HAS_YUY2TOYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { - YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2; - YUY2ToYRow = YUY2ToYRow_Any_SSE2; - if (IS_ALIGNED(width, 16)) { - YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2; - YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2; - if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) { - YUY2ToUV422Row = YUY2ToUV422Row_SSE2; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - YUY2ToYRow = YUY2ToYRow_SSE2; - } - } - } - } -#endif -#if defined(HAS_YUY2TOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { - YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2; - YUY2ToYRow = YUY2ToYRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - YUY2ToUV422Row = YUY2ToUV422Row_AVX2; - YUY2ToYRow = YUY2ToYRow_AVX2; - } - } -#endif -#if defined(HAS_YUY2TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - YUY2ToYRow = YUY2ToYRow_Any_NEON; - if (width >= 16) { - YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON; - } - if (IS_ALIGNED(width, 16)) { - YUY2ToYRow = YUY2ToYRow_NEON; - YUY2ToUV422Row = YUY2ToUV422Row_NEON; - } - } -#endif - - for (y = 0; y < height - 1; y += 2) { - CopyRow(src_y, dst_y, width); - src_y += src_stride_y; - dst_y += dst_stride_y; - - YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width); - YUY2ToYRow(src_yuy2, dst_y, width); - src_yuy2 += src_stride_yuy2; - dst_y += dst_stride_y; - dst_u += dst_stride_u; - dst_v += dst_stride_v; - } - if (height & 1) { - CopyRow(src_y, dst_y, width); - YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width); - } - return 0; -} - // Convert YUY2 to I420. LIBYUV_API int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2, @@ -519,9 +390,9 @@ int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2, int width, int height) { int y; void (*YUY2ToUVRow)(const uint8* src_yuy2, int src_stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) = YUY2ToUVRow_C; + uint8* dst_u, uint8* dst_v, int width) = YUY2ToUVRow_C; void (*YUY2ToYRow)(const uint8* src_yuy2, - uint8* dst_y, int pix) = YUY2ToYRow_C; + uint8* dst_y, int width) = YUY2ToYRow_C; // Negative height means invert the image. if (height < 0) { height = -height; @@ -529,23 +400,17 @@ int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2, src_stride_yuy2 = -src_stride_yuy2; } #if defined(HAS_YUY2TOYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { YUY2ToUVRow = YUY2ToUVRow_Any_SSE2; YUY2ToYRow = YUY2ToYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { - YUY2ToUVRow = YUY2ToUVRow_Unaligned_SSE2; - YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2; - if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) { - YUY2ToUVRow = YUY2ToUVRow_SSE2; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - YUY2ToYRow = YUY2ToYRow_SSE2; - } - } + YUY2ToUVRow = YUY2ToUVRow_SSE2; + YUY2ToYRow = YUY2ToYRow_SSE2; } } #endif #if defined(HAS_YUY2TOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { YUY2ToUVRow = YUY2ToUVRow_Any_AVX2; YUY2ToYRow = YUY2ToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { @@ -555,11 +420,9 @@ int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2, } #endif #if defined(HAS_YUY2TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { YUY2ToYRow = YUY2ToYRow_Any_NEON; - if (width >= 16) { - YUY2ToUVRow = YUY2ToUVRow_Any_NEON; - } + YUY2ToUVRow = YUY2ToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { YUY2ToYRow = YUY2ToYRow_NEON; YUY2ToUVRow = YUY2ToUVRow_NEON; @@ -592,9 +455,9 @@ int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy, int width, int height) { int y; void (*UYVYToUVRow)(const uint8* src_uyvy, int src_stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) = UYVYToUVRow_C; + uint8* dst_u, uint8* dst_v, int width) = UYVYToUVRow_C; void (*UYVYToYRow)(const uint8* src_uyvy, - uint8* dst_y, int pix) = UYVYToYRow_C; + uint8* dst_y, int width) = UYVYToYRow_C; // Negative height means invert the image. if (height < 0) { height = -height; @@ -602,23 +465,17 @@ int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy, src_stride_uyvy = -src_stride_uyvy; } #if defined(HAS_UYVYTOYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { UYVYToUVRow = UYVYToUVRow_Any_SSE2; UYVYToYRow = UYVYToYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { - UYVYToUVRow = UYVYToUVRow_Unaligned_SSE2; - UYVYToYRow = UYVYToYRow_Unaligned_SSE2; - if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) { - UYVYToUVRow = UYVYToUVRow_SSE2; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - UYVYToYRow = UYVYToYRow_SSE2; - } - } + UYVYToUVRow = UYVYToUVRow_SSE2; + UYVYToYRow = UYVYToYRow_SSE2; } } #endif #if defined(HAS_UYVYTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { UYVYToUVRow = UYVYToUVRow_Any_AVX2; UYVYToYRow = UYVYToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { @@ -628,11 +485,9 @@ int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy, } #endif #if defined(HAS_UYVYTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { UYVYToYRow = UYVYToYRow_Any_NEON; - if (width >= 16) { - UYVYToUVRow = UYVYToUVRow_Any_NEON; - } + UYVYToUVRow = UYVYToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { UYVYToYRow = UYVYToYRow_NEON; UYVYToUVRow = UYVYToUVRow_NEON; @@ -666,7 +521,7 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, int y; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; if (!src_argb || !dst_y || !dst_u || !dst_v || @@ -680,23 +535,17 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, src_stride_argb = -src_stride_argb; } #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } #endif #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBToUVRow = ARGBToUVRow_Any_AVX2; ARGBToYRow = ARGBToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { @@ -706,7 +555,7 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -714,7 +563,7 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUVRow = ARGBToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUVRow = ARGBToUVRow_NEON; @@ -748,7 +597,7 @@ int BGRAToI420(const uint8* src_bgra, int src_stride_bgra, int y; void (*BGRAToUVRow)(const uint8* src_bgra0, int src_stride_bgra, uint8* dst_u, uint8* dst_v, int width) = BGRAToUVRow_C; - void (*BGRAToYRow)(const uint8* src_bgra, uint8* dst_y, int pix) = + void (*BGRAToYRow)(const uint8* src_bgra, uint8* dst_y, int width) = BGRAToYRow_C; if (!src_bgra || !dst_y || !dst_u || !dst_v || @@ -761,23 +610,18 @@ int BGRAToI420(const uint8* src_bgra, int src_stride_bgra, src_bgra = src_bgra + (height - 1) * src_stride_bgra; src_stride_bgra = -src_stride_bgra; } -#if defined(HAS_BGRATOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_BGRATOYROW_SSSE3) && defined(HAS_BGRATOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { BGRAToUVRow = BGRAToUVRow_Any_SSSE3; BGRAToYRow = BGRAToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - BGRAToUVRow = BGRAToUVRow_Unaligned_SSSE3; - BGRAToYRow = BGRAToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16)) { - BGRAToUVRow = BGRAToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - BGRAToYRow = BGRAToYRow_SSSE3; - } - } + BGRAToUVRow = BGRAToUVRow_SSSE3; + BGRAToYRow = BGRAToYRow_SSSE3; } } -#elif defined(HAS_BGRATOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_BGRATOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { BGRAToYRow = BGRAToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { BGRAToYRow = BGRAToYRow_NEON; @@ -785,7 +629,7 @@ int BGRAToI420(const uint8* src_bgra, int src_stride_bgra, } #endif #if defined(HAS_BGRATOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { BGRAToUVRow = BGRAToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { BGRAToUVRow = BGRAToUVRow_NEON; @@ -819,7 +663,7 @@ int ABGRToI420(const uint8* src_abgr, int src_stride_abgr, int y; void (*ABGRToUVRow)(const uint8* src_abgr0, int src_stride_abgr, uint8* dst_u, uint8* dst_v, int width) = ABGRToUVRow_C; - void (*ABGRToYRow)(const uint8* src_abgr, uint8* dst_y, int pix) = + void (*ABGRToYRow)(const uint8* src_abgr, uint8* dst_y, int width) = ABGRToYRow_C; if (!src_abgr || !dst_y || !dst_u || !dst_v || @@ -832,23 +676,18 @@ int ABGRToI420(const uint8* src_abgr, int src_stride_abgr, src_abgr = src_abgr + (height - 1) * src_stride_abgr; src_stride_abgr = -src_stride_abgr; } -#if defined(HAS_ABGRTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ABGRTOYROW_SSSE3) && defined(HAS_ABGRTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { ABGRToUVRow = ABGRToUVRow_Any_SSSE3; ABGRToYRow = ABGRToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ABGRToUVRow = ABGRToUVRow_Unaligned_SSSE3; - ABGRToYRow = ABGRToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_abgr, 16) && IS_ALIGNED(src_stride_abgr, 16)) { - ABGRToUVRow = ABGRToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ABGRToYRow = ABGRToYRow_SSSE3; - } - } + ABGRToUVRow = ABGRToUVRow_SSSE3; + ABGRToYRow = ABGRToYRow_SSSE3; } } -#elif defined(HAS_ABGRTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ABGRTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ABGRToYRow = ABGRToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ABGRToYRow = ABGRToYRow_NEON; @@ -856,7 +695,7 @@ int ABGRToI420(const uint8* src_abgr, int src_stride_abgr, } #endif #if defined(HAS_ABGRTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { ABGRToUVRow = ABGRToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ABGRToUVRow = ABGRToUVRow_NEON; @@ -890,7 +729,7 @@ int RGBAToI420(const uint8* src_rgba, int src_stride_rgba, int y; void (*RGBAToUVRow)(const uint8* src_rgba0, int src_stride_rgba, uint8* dst_u, uint8* dst_v, int width) = RGBAToUVRow_C; - void (*RGBAToYRow)(const uint8* src_rgba, uint8* dst_y, int pix) = + void (*RGBAToYRow)(const uint8* src_rgba, uint8* dst_y, int width) = RGBAToYRow_C; if (!src_rgba || !dst_y || !dst_u || !dst_v || @@ -903,23 +742,18 @@ int RGBAToI420(const uint8* src_rgba, int src_stride_rgba, src_rgba = src_rgba + (height - 1) * src_stride_rgba; src_stride_rgba = -src_stride_rgba; } -#if defined(HAS_RGBATOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_RGBATOYROW_SSSE3) && defined(HAS_RGBATOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { RGBAToUVRow = RGBAToUVRow_Any_SSSE3; RGBAToYRow = RGBAToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - RGBAToUVRow = RGBAToUVRow_Unaligned_SSSE3; - RGBAToYRow = RGBAToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_rgba, 16) && IS_ALIGNED(src_stride_rgba, 16)) { - RGBAToUVRow = RGBAToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - RGBAToYRow = RGBAToYRow_SSSE3; - } - } + RGBAToUVRow = RGBAToUVRow_SSSE3; + RGBAToYRow = RGBAToYRow_SSSE3; } } -#elif defined(HAS_RGBATOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_RGBATOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { RGBAToYRow = RGBAToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RGBAToYRow = RGBAToYRow_NEON; @@ -927,7 +761,7 @@ int RGBAToI420(const uint8* src_rgba, int src_stride_rgba, } #endif #if defined(HAS_RGBATOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { RGBAToUVRow = RGBAToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { RGBAToUVRow = RGBAToUVRow_NEON; @@ -962,14 +796,14 @@ int RGB24ToI420(const uint8* src_rgb24, int src_stride_rgb24, #if defined(HAS_RGB24TOYROW_NEON) void (*RGB24ToUVRow)(const uint8* src_rgb24, int src_stride_rgb24, uint8* dst_u, uint8* dst_v, int width) = RGB24ToUVRow_C; - void (*RGB24ToYRow)(const uint8* src_rgb24, uint8* dst_y, int pix) = + void (*RGB24ToYRow)(const uint8* src_rgb24, uint8* dst_y, int width) = RGB24ToYRow_C; #else - void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = RGB24ToARGBRow_C; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; #endif if (!src_rgb24 || !dst_y || !dst_u || !dst_v || @@ -983,54 +817,51 @@ int RGB24ToI420(const uint8* src_rgb24, int src_stride_rgb24, src_stride_rgb24 = -src_stride_rgb24; } +// Neon version does direct RGB24 to YUV. #if defined(HAS_RGB24TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { + RGB24ToUVRow = RGB24ToUVRow_Any_NEON; RGB24ToYRow = RGB24ToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RGB24ToYRow = RGB24ToYRow_NEON; + if (IS_ALIGNED(width, 16)) { + RGB24ToUVRow = RGB24ToUVRow_NEON; + } } } -#endif -#if defined(HAS_RGB24TOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { - RGB24ToUVRow = RGB24ToUVRow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - RGB24ToUVRow = RGB24ToUVRow_NEON; - } - } -#endif +// Other platforms do intermediate conversion from RGB24 to ARGB. +#else #if defined(HAS_RGB24TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { RGB24ToARGBRow = RGB24ToARGBRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; + ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToYRow = ARGBToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; } } -#endif // HAS_ARGBTOUVROW_SSSE3 - +#endif { -#if !defined(HAS_RGB24TOYROW_NEON) // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; + const int kRowSize = (width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); #endif @@ -1063,8 +894,8 @@ int RGB24ToI420(const uint8* src_rgb24, int src_stride_rgb24, } #if !defined(HAS_RGB24TOYROW_NEON) free_aligned_buffer_64(row); -#endif } +#endif return 0; } @@ -1079,14 +910,14 @@ int RAWToI420(const uint8* src_raw, int src_stride_raw, #if defined(HAS_RAWTOYROW_NEON) void (*RAWToUVRow)(const uint8* src_raw, int src_stride_raw, uint8* dst_u, uint8* dst_v, int width) = RAWToUVRow_C; - void (*RAWToYRow)(const uint8* src_raw, uint8* dst_y, int pix) = + void (*RAWToYRow)(const uint8* src_raw, uint8* dst_y, int width) = RAWToYRow_C; #else - void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = RAWToARGBRow_C; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; #endif if (!src_raw || !dst_y || !dst_u || !dst_v || @@ -1100,86 +931,85 @@ int RAWToI420(const uint8* src_raw, int src_stride_raw, src_stride_raw = -src_stride_raw; } +// Neon version does direct RAW to YUV. #if defined(HAS_RAWTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { + RAWToUVRow = RAWToUVRow_Any_NEON; RAWToYRow = RAWToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RAWToYRow = RAWToYRow_NEON; + if (IS_ALIGNED(width, 16)) { + RAWToUVRow = RAWToUVRow_NEON; + } } } -#endif -#if defined(HAS_RAWTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { - RAWToUVRow = RAWToUVRow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - RAWToUVRow = RAWToUVRow_NEON; - } - } -#endif +// Other platforms do intermediate conversion from RAW to ARGB. +#else #if defined(HAS_RAWTOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { RAWToARGBRow = RAWToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { RAWToARGBRow = RAWToARGBRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; + ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToYRow = ARGBToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; } } -#endif // HAS_ARGBTOUVROW_SSSE3 - +#endif { // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; + const int kRowSize = (width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); +#endif for (y = 0; y < height - 1; y += 2) { - #if defined(HAS_RAWTOYROW_NEON) +#if defined(HAS_RAWTOYROW_NEON) RAWToUVRow(src_raw, src_stride_raw, dst_u, dst_v, width); RAWToYRow(src_raw, dst_y, width); RAWToYRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width); - #else +#else RAWToARGBRow(src_raw, row, width); RAWToARGBRow(src_raw + src_stride_raw, row + kRowSize, width); ARGBToUVRow(row, kRowSize, dst_u, dst_v, width); ARGBToYRow(row, dst_y, width); ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width); - #endif +#endif src_raw += src_stride_raw * 2; dst_y += dst_stride_y * 2; dst_u += dst_stride_u; dst_v += dst_stride_v; } if (height & 1) { - #if defined(HAS_RAWTOYROW_NEON) +#if defined(HAS_RAWTOYROW_NEON) RAWToUVRow(src_raw, 0, dst_u, dst_v, width); RAWToYRow(src_raw, dst_y, width); - #else +#else RAWToARGBRow(src_raw, row, width); ARGBToUVRow(row, 0, dst_u, dst_v, width); ARGBToYRow(row, dst_y, width); - #endif +#endif } - #if !defined(HAS_RAWTOYROW_NEON) +#if !defined(HAS_RAWTOYROW_NEON) free_aligned_buffer_64(row); - #endif } +#endif return 0; } @@ -1194,14 +1024,14 @@ int RGB565ToI420(const uint8* src_rgb565, int src_stride_rgb565, #if defined(HAS_RGB565TOYROW_NEON) void (*RGB565ToUVRow)(const uint8* src_rgb565, int src_stride_rgb565, uint8* dst_u, uint8* dst_v, int width) = RGB565ToUVRow_C; - void (*RGB565ToYRow)(const uint8* src_rgb565, uint8* dst_y, int pix) = + void (*RGB565ToYRow)(const uint8* src_rgb565, uint8* dst_y, int width) = RGB565ToYRow_C; #else - void (*RGB565ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*RGB565ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = RGB565ToARGBRow_C; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; #endif if (!src_rgb565 || !dst_y || !dst_u || !dst_v || @@ -1215,54 +1045,59 @@ int RGB565ToI420(const uint8* src_rgb565, int src_stride_rgb565, src_stride_rgb565 = -src_stride_rgb565; } +// Neon version does direct RGB565 to YUV. #if defined(HAS_RGB565TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { + RGB565ToUVRow = RGB565ToUVRow_Any_NEON; RGB565ToYRow = RGB565ToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RGB565ToYRow = RGB565ToYRow_NEON; - } - if (width >= 16) { - RGB565ToUVRow = RGB565ToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { RGB565ToUVRow = RGB565ToUVRow_NEON; } } } -#else // HAS_RGB565TOYROW_NEON - +// Other platforms do intermediate conversion from RGB565 to ARGB. +#else #if defined(HAS_RGB565TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8) { + if (TestCpuFlag(kCpuHasSSE2)) { RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { RGB565ToARGBRow = RGB565ToARGBRow_SSE2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; +#if defined(HAS_RGB565TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; + RGB565ToARGBRow = RGB565ToARGBRow_AVX2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } -#endif // HAS_ARGBTOUVROW_SSSE3 -#endif // HAS_RGB565TOYROW_NEON - +#endif +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif { -#if !defined(HAS_RGB565TOYROW_NEON) // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; + const int kRowSize = (width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); #endif @@ -1295,8 +1130,8 @@ int RGB565ToI420(const uint8* src_rgb565, int src_stride_rgb565, } #if !defined(HAS_RGB565TOYROW_NEON) free_aligned_buffer_64(row); -#endif } +#endif return 0; } @@ -1311,14 +1146,14 @@ int ARGB1555ToI420(const uint8* src_argb1555, int src_stride_argb1555, #if defined(HAS_ARGB1555TOYROW_NEON) void (*ARGB1555ToUVRow)(const uint8* src_argb1555, int src_stride_argb1555, uint8* dst_u, uint8* dst_v, int width) = ARGB1555ToUVRow_C; - void (*ARGB1555ToYRow)(const uint8* src_argb1555, uint8* dst_y, int pix) = + void (*ARGB1555ToYRow)(const uint8* src_argb1555, uint8* dst_y, int width) = ARGB1555ToYRow_C; #else - void (*ARGB1555ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*ARGB1555ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = ARGB1555ToARGBRow_C; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; #endif if (!src_argb1555 || !dst_y || !dst_u || !dst_v || @@ -1332,56 +1167,62 @@ int ARGB1555ToI420(const uint8* src_argb1555, int src_stride_argb1555, src_stride_argb1555 = -src_stride_argb1555; } +// Neon version does direct ARGB1555 to YUV. #if defined(HAS_ARGB1555TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { + ARGB1555ToUVRow = ARGB1555ToUVRow_Any_NEON; ARGB1555ToYRow = ARGB1555ToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGB1555ToYRow = ARGB1555ToYRow_NEON; - } - if (width >= 16) { - ARGB1555ToUVRow = ARGB1555ToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGB1555ToUVRow = ARGB1555ToUVRow_NEON; } } } -#else // HAS_ARGB1555TOYROW_NEON - +// Other platforms do intermediate conversion from ARGB1555 to ARGB. +#else #if defined(HAS_ARGB1555TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; +#if defined(HAS_ARGB1555TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } -#endif // HAS_ARGBTOUVROW_SSSE3 -#endif // HAS_ARGB1555TOYROW_NEON - +#endif +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif { -#if !defined(HAS_ARGB1555TOYROW_NEON) // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; + const int kRowSize = (width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); #endif + for (y = 0; y < height - 1; y += 2) { #if defined(HAS_ARGB1555TOYROW_NEON) ARGB1555ToUVRow(src_argb1555, src_stride_argb1555, dst_u, dst_v, width); @@ -1412,9 +1253,9 @@ int ARGB1555ToI420(const uint8* src_argb1555, int src_stride_argb1555, #endif } #if !defined(HAS_ARGB1555TOYROW_NEON) - free_aligned_buffer_64(row); -#endif + free_aligned_buffer_64(row); } +#endif return 0; } @@ -1429,14 +1270,14 @@ int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444, #if defined(HAS_ARGB4444TOYROW_NEON) void (*ARGB4444ToUVRow)(const uint8* src_argb4444, int src_stride_argb4444, uint8* dst_u, uint8* dst_v, int width) = ARGB4444ToUVRow_C; - void (*ARGB4444ToYRow)(const uint8* src_argb4444, uint8* dst_y, int pix) = + void (*ARGB4444ToYRow)(const uint8* src_argb4444, uint8* dst_y, int width) = ARGB4444ToYRow_C; #else - void (*ARGB4444ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*ARGB4444ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = ARGB4444ToARGBRow_C; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; #endif if (!src_argb4444 || !dst_y || !dst_u || !dst_v || @@ -1450,54 +1291,59 @@ int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444, src_stride_argb4444 = -src_stride_argb4444; } +// Neon version does direct ARGB4444 to YUV. #if defined(HAS_ARGB4444TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { + ARGB4444ToUVRow = ARGB4444ToUVRow_Any_NEON; ARGB4444ToYRow = ARGB4444ToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGB4444ToYRow = ARGB4444ToYRow_NEON; - } - if (width >= 16) { - ARGB4444ToUVRow = ARGB4444ToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGB4444ToUVRow = ARGB4444ToUVRow_NEON; } } } -#else // HAS_ARGB4444TOYROW_NEON - +// Other platforms do intermediate conversion from ARGB4444 to ARGB. +#else #if defined(HAS_ARGB4444TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; +#if defined(HAS_ARGB4444TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2; } } #endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } -#endif // HAS_ARGBTOUVROW_SSSE3 -#endif // HAS_ARGB4444TOYROW_NEON - +#endif +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif { -#if !defined(HAS_ARGB4444TOYROW_NEON) // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; + const int kRowSize = (width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); #endif @@ -1532,8 +1378,8 @@ int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444, } #if !defined(HAS_ARGB4444TOYROW_NEON) free_aligned_buffer_64(row); -#endif } +#endif return 0; } diff --git a/TMessagesProj/jni/libyuv/source/convert_argb.cc b/TMessagesProj/jni/libyuv/source/convert_argb.cc index ac0bc3d1..cf3d7228 100644 --- a/TMessagesProj/jni/libyuv/source/convert_argb.cc +++ b/TMessagesProj/jni/libyuv/source/convert_argb.cc @@ -11,7 +11,6 @@ #include "libyuv/convert_argb.h" #include "libyuv/cpu_id.h" -#include "libyuv/format_conversion.h" #ifdef HAVE_JPEG #include "libyuv/mjpeg_decoder.h" #endif @@ -45,21 +44,21 @@ int ARGBCopy(const uint8* src_argb, int src_stride_argb, return 0; } -// Convert I444 to ARGB. -LIBYUV_API -int I444ToARGB(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_argb, int dst_stride_argb, - int width, int height) { +// Convert I422 to ARGB with matrix +static int I420ToARGBMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, int height) { int y; - void (*I444ToARGBRow)(const uint8* y_buf, + void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, - int width) = I444ToARGBRow_C; - if (!src_y || !src_u || !src_v || - !dst_argb || + const struct YuvConstants* yuvconstants, + int width) = I422ToARGBRow_C; + if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { return -1; } @@ -69,56 +68,155 @@ int I444ToARGB(const uint8* src_y, int src_stride_y, dst_argb = dst_argb + (height - 1) * dst_stride_argb; dst_stride_argb = -dst_stride_argb; } - // Coalesce rows. - if (src_stride_y == width && - src_stride_u == width && - src_stride_v == width && - dst_stride_argb == width * 4) { - width *= height; - height = 1; - src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; - } -#if defined(HAS_I444TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I444ToARGBRow = I444ToARGBRow_Any_SSSE3; +#if defined(HAS_I422TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToARGBRow = I422ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I444ToARGBRow = I444ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I444ToARGBRow = I444ToARGBRow_SSSE3; - } + I422ToARGBRow = I422ToARGBRow_SSSE3; } } -#elif defined(HAS_I444TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I444ToARGBRow = I444ToARGBRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I444ToARGBRow = I444ToARGBRow_NEON; +#endif +#if defined(HAS_I422TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToARGBRow = I422ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGBRow = I422ToARGBRow_AVX2; } } #endif +#if defined(HAS_I422TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToARGBRow = I422ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_NEON; + } + } +#endif +#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && + IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { + I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; + } +#endif for (y = 0; y < height; ++y) { - I444ToARGBRow(src_y, src_u, src_v, dst_argb, width); + I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); dst_argb += dst_stride_argb; src_y += src_stride_y; - src_u += src_stride_u; - src_v += src_stride_v; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } } return 0; } -// Convert I422 to ARGB. +// Convert I420 to ARGB. LIBYUV_API -int I422ToARGB(const uint8* src_y, int src_stride_y, +int I420ToARGB(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, uint8* dst_argb, int dst_stride_argb, int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvI601Constants, + width, height); +} + +// Convert I420 to ABGR. +LIBYUV_API +int I420ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuI601Constants, // Use Yvu matrix + width, height); +} + +// Convert J420 to ARGB. +LIBYUV_API +int J420ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvJPEGConstants, + width, height); +} + +// Convert J420 to ABGR. +LIBYUV_API +int J420ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuJPEGConstants, // Use Yvu matrix + width, height); +} + +// Convert H420 to ARGB. +LIBYUV_API +int H420ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvH709Constants, + width, height); +} + +// Convert H420 to ABGR. +LIBYUV_API +int H420ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I420ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuH709Constants, // Use Yvu matrix + width, height); +} + +// Convert I422 to ARGB with matrix +static int I422ToARGBMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, int height) { int y; void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = I422ToARGBRow_C; if (!src_y || !src_u || !src_v || !dst_argb || @@ -141,18 +239,15 @@ int I422ToARGB(const uint8* src_y, int src_stride_y, src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; } #if defined(HAS_I422TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I422ToARGBRow = I422ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I422ToARGBRow = I422ToARGBRow_SSSE3; - } + I422ToARGBRow = I422ToARGBRow_SSSE3; } } #endif #if defined(HAS_I422TOARGBROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { + if (TestCpuFlag(kCpuHasAVX2)) { I422ToARGBRow = I422ToARGBRow_Any_AVX2; if (IS_ALIGNED(width, 16)) { I422ToARGBRow = I422ToARGBRow_AVX2; @@ -160,7 +255,7 @@ int I422ToARGB(const uint8* src_y, int src_stride_y, } #endif #if defined(HAS_I422TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { I422ToARGBRow = I422ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { I422ToARGBRow = I422ToARGBRow_NEON; @@ -178,7 +273,7 @@ int I422ToARGB(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - I422ToARGBRow(src_y, src_u, src_v, dst_argb, width); + I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); dst_argb += dst_stride_argb; src_y += src_stride_y; src_u += src_stride_u; @@ -187,6 +282,210 @@ int I422ToARGB(const uint8* src_y, int src_stride_y, return 0; } +// Convert I422 to ARGB. +LIBYUV_API +int I422ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvI601Constants, + width, height); +} + +// Convert I422 to ABGR. +LIBYUV_API +int I422ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuI601Constants, // Use Yvu matrix + width, height); +} + +// Convert J422 to ARGB. +LIBYUV_API +int J422ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvJPEGConstants, + width, height); +} + +// Convert J422 to ABGR. +LIBYUV_API +int J422ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuJPEGConstants, // Use Yvu matrix + width, height); +} + +// Convert H422 to ARGB. +LIBYUV_API +int H422ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvH709Constants, + width, height); +} + +// Convert H422 to ABGR. +LIBYUV_API +int H422ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I422ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuH709Constants, // Use Yvu matrix + width, height); +} + +// Convert I444 to ARGB with matrix +static int I444ToARGBMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, int height) { + int y; + void (*I444ToARGBRow)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* rgb_buf, + const struct YuvConstants* yuvconstants, + int width) = I444ToARGBRow_C; + if (!src_y || !src_u || !src_v || + !dst_argb || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_argb = dst_argb + (height - 1) * dst_stride_argb; + dst_stride_argb = -dst_stride_argb; + } + // Coalesce rows. + if (src_stride_y == width && + src_stride_u == width && + src_stride_v == width && + dst_stride_argb == width * 4) { + width *= height; + height = 1; + src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; + } +#if defined(HAS_I444TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I444ToARGBRow = I444ToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + I444ToARGBRow = I444ToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_I444TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I444ToARGBRow = I444ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I444ToARGBRow = I444ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I444TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I444ToARGBRow = I444ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I444ToARGBRow = I444ToARGBRow_NEON; + } + } +#endif + + for (y = 0; y < height; ++y) { + I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); + dst_argb += dst_stride_argb; + src_y += src_stride_y; + src_u += src_stride_u; + src_v += src_stride_v; + } + return 0; +} + +// Convert I444 to ARGB. +LIBYUV_API +int I444ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I444ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvI601Constants, + width, height); +} + +// Convert I444 to ABGR. +LIBYUV_API +int I444ToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height) { + return I444ToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_abgr, dst_stride_abgr, + &kYvuI601Constants, // Use Yvu matrix + width, height); +} + +// Convert J444 to ARGB. +LIBYUV_API +int J444ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + return I444ToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_argb, dst_stride_argb, + &kYuvJPEGConstants, + width, height); +} + // Convert I411 to ARGB. LIBYUV_API int I411ToARGB(const uint8* src_y, int src_stride_y, @@ -199,6 +498,7 @@ int I411ToARGB(const uint8* src_y, int src_stride_y, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = I411ToARGBRow_C; if (!src_y || !src_u || !src_v || !dst_argb || @@ -221,17 +521,23 @@ int I411ToARGB(const uint8* src_y, int src_stride_y, src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; } #if defined(HAS_I411TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I411ToARGBRow = I411ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I411ToARGBRow = I411ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I411ToARGBRow = I411ToARGBRow_SSSE3; - } + I411ToARGBRow = I411ToARGBRow_SSSE3; } } -#elif defined(HAS_I411TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_I411TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I411ToARGBRow = I411ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I411ToARGBRow = I411ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I411TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I411ToARGBRow = I411ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { I411ToARGBRow = I411ToARGBRow_NEON; @@ -240,7 +546,7 @@ int I411ToARGB(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - I411ToARGBRow(src_y, src_u, src_v, dst_argb, width); + I411ToARGBRow(src_y, src_u, src_v, dst_argb, &kYuvI601Constants, width); dst_argb += dst_stride_argb; src_y += src_stride_y; src_u += src_stride_u; @@ -249,15 +555,152 @@ int I411ToARGB(const uint8* src_y, int src_stride_y, return 0; } +// Convert I420 with Alpha to preattenuated ARGB. +static int I420AlphaToARGBMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + const uint8* src_a, int src_stride_a, + uint8* dst_argb, int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, int height, int attenuate) { + int y; + void (*I422AlphaToARGBRow)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) = I422AlphaToARGBRow_C; + void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb, + int width) = ARGBAttenuateRow_C; + if (!src_y || !src_u || !src_v || !dst_argb || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_argb = dst_argb + (height - 1) * dst_stride_argb; + dst_stride_argb = -dst_stride_argb; + } +#if defined(HAS_I422ALPHATOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_I422ALPHATOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I422ALPHATOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_NEON; + } + } +#endif +#if defined(HAS_I422ALPHATOARGBROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && + IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { + I422AlphaToARGBRow = I422AlphaToARGBRow_MIPS_DSPR2; + } +#endif +#if defined(HAS_ARGBATTENUATEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3; + if (IS_ALIGNED(width, 4)) { + ARGBAttenuateRow = ARGBAttenuateRow_SSSE3; + } + } +#endif +#if defined(HAS_ARGBATTENUATEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBAttenuateRow = ARGBAttenuateRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBATTENUATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBAttenuateRow = ARGBAttenuateRow_NEON; + } + } +#endif + + for (y = 0; y < height; ++y) { + I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants, + width); + if (attenuate) { + ARGBAttenuateRow(dst_argb, dst_argb, width); + } + dst_argb += dst_stride_argb; + src_a += src_stride_a; + src_y += src_stride_y; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } + } + return 0; +} + +// Convert I420 with Alpha to ARGB. +LIBYUV_API +int I420AlphaToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + const uint8* src_a, int src_stride_a, + uint8* dst_argb, int dst_stride_argb, + int width, int height, int attenuate) { + return I420AlphaToARGBMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + src_a, src_stride_a, + dst_argb, dst_stride_argb, + &kYuvI601Constants, + width, height, attenuate); +} + +// Convert I420 with Alpha to ABGR. +LIBYUV_API +int I420AlphaToABGR(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + const uint8* src_a, int src_stride_a, + uint8* dst_abgr, int dst_stride_abgr, + int width, int height, int attenuate) { + return I420AlphaToARGBMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + src_a, src_stride_a, + dst_abgr, dst_stride_abgr, + &kYvuI601Constants, // Use Yvu matrix + width, height, attenuate); +} + // Convert I400 to ARGB. LIBYUV_API -int I400ToARGB_Reference(const uint8* src_y, int src_stride_y, - uint8* dst_argb, int dst_stride_argb, - int width, int height) { +int I400ToARGB(const uint8* src_y, int src_stride_y, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { int y; - void (*YToARGBRow)(const uint8* y_buf, + void (*I400ToARGBRow)(const uint8* y_buf, uint8* rgb_buf, - int width) = YToARGBRow_C; + int width) = I400ToARGBRow_C; if (!src_y || !dst_argb || width <= 0 || height == 0) { return -1; @@ -275,39 +718,47 @@ int I400ToARGB_Reference(const uint8* src_y, int src_stride_y, height = 1; src_stride_y = dst_stride_argb = 0; } -#if defined(HAS_YTOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - YToARGBRow = YToARGBRow_Any_SSE2; +#if defined(HAS_I400TOARGBROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + I400ToARGBRow = I400ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { - YToARGBRow = YToARGBRow_SSE2; + I400ToARGBRow = I400ToARGBRow_SSE2; } } -#elif defined(HAS_YTOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - YToARGBRow = YToARGBRow_Any_NEON; +#endif +#if defined(HAS_I400TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I400ToARGBRow = I400ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I400ToARGBRow = I400ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I400TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I400ToARGBRow = I400ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { - YToARGBRow = YToARGBRow_NEON; + I400ToARGBRow = I400ToARGBRow_NEON; } } #endif for (y = 0; y < height; ++y) { - YToARGBRow(src_y, dst_argb, width); + I400ToARGBRow(src_y, dst_argb, width); dst_argb += dst_stride_argb; src_y += src_stride_y; } return 0; } -// Convert I400 to ARGB. +// Convert J400 to ARGB. LIBYUV_API -int I400ToARGB(const uint8* src_y, int src_stride_y, +int J400ToARGB(const uint8* src_y, int src_stride_y, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*I400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) = - I400ToARGBRow_C; + void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int width) = + J400ToARGBRow_C; if (!src_y || !dst_argb || width <= 0 || height == 0) { return -1; @@ -325,26 +776,32 @@ int I400ToARGB(const uint8* src_y, int src_stride_y, height = 1; src_stride_y = dst_stride_argb = 0; } -#if defined(HAS_I400TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8) { - I400ToARGBRow = I400ToARGBRow_Any_SSE2; +#if defined(HAS_J400TOARGBROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + J400ToARGBRow = J400ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { - I400ToARGBRow = I400ToARGBRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I400ToARGBRow = I400ToARGBRow_SSE2; - } + J400ToARGBRow = J400ToARGBRow_SSE2; } } -#elif defined(HAS_I400TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I400ToARGBRow = I400ToARGBRow_Any_NEON; +#endif +#if defined(HAS_J400TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + J400ToARGBRow = J400ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + J400ToARGBRow = J400ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_J400TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + J400ToARGBRow = J400ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { - I400ToARGBRow = I400ToARGBRow_NEON; + J400ToARGBRow = J400ToARGBRow_NEON; } } #endif for (y = 0; y < height; ++y) { - I400ToARGBRow(src_y, dst_argb, width); + J400ToARGBRow(src_y, dst_argb, width); src_y += src_stride_y; dst_argb += dst_stride_argb; } @@ -427,7 +884,7 @@ int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = RGB24ToARGBRow_C; if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) { @@ -447,15 +904,15 @@ int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24, src_stride_rgb24 = dst_stride_argb = 0; } #if defined(HAS_RGB24TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3)) { RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { RGB24ToARGBRow = RGB24ToARGBRow_SSSE3; } } -#elif defined(HAS_RGB24TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_RGB24TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RGB24ToARGBRow = RGB24ToARGBRow_NEON; @@ -477,7 +934,7 @@ int RAWToARGB(const uint8* src_raw, int src_stride_raw, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = + void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = RAWToARGBRow_C; if (!src_raw || !dst_argb || width <= 0 || height == 0) { @@ -497,15 +954,15 @@ int RAWToARGB(const uint8* src_raw, int src_stride_raw, src_stride_raw = dst_stride_argb = 0; } #if defined(HAS_RAWTOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3)) { RAWToARGBRow = RAWToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { RAWToARGBRow = RAWToARGBRow_SSSE3; } } -#elif defined(HAS_RAWTOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_RAWTOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { RAWToARGBRow = RAWToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RAWToARGBRow = RAWToARGBRow_NEON; @@ -527,7 +984,7 @@ int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) = + void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int width) = RGB565ToARGBRow_C; if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) { @@ -547,15 +1004,23 @@ int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565, src_stride_rgb565 = dst_stride_argb = 0; } #if defined(HAS_RGB565TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { RGB565ToARGBRow = RGB565ToARGBRow_SSE2; } } -#elif defined(HAS_RGB565TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_RGB565TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + RGB565ToARGBRow = RGB565ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_RGB565TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { RGB565ToARGBRow = RGB565ToARGBRow_NEON; @@ -578,7 +1043,7 @@ int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555, int width, int height) { int y; void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb, - int pix) = ARGB1555ToARGBRow_C; + int width) = ARGB1555ToARGBRow_C; if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) { return -1; @@ -597,15 +1062,23 @@ int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555, src_stride_argb1555 = dst_stride_argb = 0; } #if defined(HAS_ARGB1555TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2; } } -#elif defined(HAS_ARGB1555TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGB1555TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_ARGB1555TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON; @@ -628,7 +1101,7 @@ int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444, int width, int height) { int y; void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb, - int pix) = ARGB4444ToARGBRow_C; + int width) = ARGB4444ToARGBRow_C; if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) { return -1; @@ -647,15 +1120,23 @@ int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444, src_stride_argb4444 = dst_stride_argb = 0; } #if defined(HAS_ARGB4444TOARGBROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2; if (IS_ALIGNED(width, 8)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2; } } -#elif defined(HAS_ARGB4444TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGB4444TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_ARGB4444TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON; @@ -681,6 +1162,7 @@ int NV12ToARGB(const uint8* src_y, int src_stride_y, void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C; if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) { @@ -693,17 +1175,23 @@ int NV12ToARGB(const uint8* src_y, int src_stride_y, dst_stride_argb = -dst_stride_argb; } #if defined(HAS_NV12TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - NV12ToARGBRow = NV12ToARGBRow_SSSE3; - } + NV12ToARGBRow = NV12ToARGBRow_SSSE3; } } -#elif defined(HAS_NV12TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_NV12TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + NV12ToARGBRow = NV12ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + NV12ToARGBRow = NV12ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_NV12TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { NV12ToARGBRow = NV12ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { NV12ToARGBRow = NV12ToARGBRow_NEON; @@ -712,7 +1200,7 @@ int NV12ToARGB(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - NV12ToARGBRow(src_y, src_uv, dst_argb, width); + NV12ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width); dst_argb += dst_stride_argb; src_y += src_stride_y; if (y & 1) { @@ -732,6 +1220,7 @@ int NV21ToARGB(const uint8* src_y, int src_stride_y, void (*NV21ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C; if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) { @@ -744,18 +1233,23 @@ int NV21ToARGB(const uint8* src_y, int src_stride_y, dst_stride_argb = -dst_stride_argb; } #if defined(HAS_NV21TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - NV21ToARGBRow = NV21ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - NV21ToARGBRow = NV21ToARGBRow_SSSE3; - } + NV21ToARGBRow = NV21ToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_NV21TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + NV21ToARGBRow = NV21ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + NV21ToARGBRow = NV21ToARGBRow_AVX2; } } #endif #if defined(HAS_NV21TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { NV21ToARGBRow = NV21ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { NV21ToARGBRow = NV21ToARGBRow_NEON; @@ -764,7 +1258,7 @@ int NV21ToARGB(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - NV21ToARGBRow(src_y, src_uv, dst_argb, width); + NV21ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width); dst_argb += dst_stride_argb; src_y += src_stride_y; if (y & 1) { @@ -783,6 +1277,7 @@ int M420ToARGB(const uint8* src_m420, int src_stride_m420, void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C; if (!src_m420 || !dst_argb || width <= 0 || height == 0) { @@ -795,17 +1290,23 @@ int M420ToARGB(const uint8* src_m420, int src_stride_m420, dst_stride_argb = -dst_stride_argb; } #if defined(HAS_NV12TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - NV12ToARGBRow = NV12ToARGBRow_SSSE3; - } + NV12ToARGBRow = NV12ToARGBRow_SSSE3; } } -#elif defined(HAS_NV12TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_NV12TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + NV12ToARGBRow = NV12ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + NV12ToARGBRow = NV12ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_NV12TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { NV12ToARGBRow = NV12ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { NV12ToARGBRow = NV12ToARGBRow_NEON; @@ -814,14 +1315,16 @@ int M420ToARGB(const uint8* src_m420, int src_stride_m420, #endif for (y = 0; y < height - 1; y += 2) { - NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width); + NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, + &kYuvI601Constants, width); NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2, - dst_argb + dst_stride_argb, width); + dst_argb + dst_stride_argb, &kYuvI601Constants, width); dst_argb += dst_stride_argb * 2; src_m420 += src_stride_m420 * 3; } if (height & 1) { - NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width); + NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, + &kYuvI601Constants, width); } return 0; } @@ -832,7 +1335,10 @@ int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) = + void (*YUY2ToARGBRow)(const uint8* src_yuy2, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) = YUY2ToARGBRow_C; if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) { @@ -852,19 +1358,23 @@ int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, src_stride_yuy2 = dst_stride_argb = 0; } #if defined(HAS_YUY2TOARGBROW_SSSE3) - // Posix is 16, Windows is 8. - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - YUY2ToARGBRow = YUY2ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - YUY2ToARGBRow = YUY2ToARGBRow_SSSE3; - } + YUY2ToARGBRow = YUY2ToARGBRow_SSSE3; } } -#elif defined(HAS_YUY2TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_YUY2TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + YUY2ToARGBRow = YUY2ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_YUY2TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { YUY2ToARGBRow = YUY2ToARGBRow_NEON; @@ -872,7 +1382,7 @@ int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, } #endif for (y = 0; y < height; ++y) { - YUY2ToARGBRow(src_yuy2, dst_argb, width); + YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width); src_yuy2 += src_stride_yuy2; dst_argb += dst_stride_argb; } @@ -885,7 +1395,10 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, uint8* dst_argb, int dst_stride_argb, int width, int height) { int y; - void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) = + void (*UYVYToARGBRow)(const uint8* src_uyvy, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) = UYVYToARGBRow_C; if (!src_uyvy || !dst_argb || width <= 0 || height == 0) { @@ -905,19 +1418,23 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, src_stride_uyvy = dst_stride_argb = 0; } #if defined(HAS_UYVYTOARGBROW_SSSE3) - // Posix is 16, Windows is 8. - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - UYVYToARGBRow = UYVYToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - UYVYToARGBRow = UYVYToARGBRow_SSSE3; - } + UYVYToARGBRow = UYVYToARGBRow_SSSE3; } } -#elif defined(HAS_UYVYTOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_UYVYTOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + UYVYToARGBRow = UYVYToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + UYVYToARGBRow = UYVYToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_UYVYTOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { UYVYToARGBRow = UYVYToARGBRow_Any_NEON; if (IS_ALIGNED(width, 8)) { UYVYToARGBRow = UYVYToARGBRow_NEON; @@ -925,7 +1442,7 @@ int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, } #endif for (y = 0; y < height; ++y) { - UYVYToARGBRow(src_uyvy, dst_argb, width); + UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width); src_uyvy += src_stride_uyvy; dst_argb += dst_stride_argb; } diff --git a/TMessagesProj/jni/libyuv/source/convert_from.cc b/TMessagesProj/jni/libyuv/source/convert_from.cc index c1a2f62f..9c138d93 100644 --- a/TMessagesProj/jni/libyuv/source/convert_from.cc +++ b/TMessagesProj/jni/libyuv/source/convert_from.cc @@ -13,7 +13,6 @@ #include "libyuv/basic_types.h" #include "libyuv/convert.h" // For I420Copy #include "libyuv/cpu_id.h" -#include "libyuv/format_conversion.h" #include "libyuv/planar_functions.h" #include "libyuv/rotate.h" #include "libyuv/scale.h" // For ScalePlane() @@ -174,14 +173,15 @@ int I422ToYUY2(const uint8* src_y, int src_stride_y, src_stride_y = src_stride_u = src_stride_v = dst_stride_yuy2 = 0; } #if defined(HAS_I422TOYUY2ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_SSE2; } } -#elif defined(HAS_I422TOYUY2ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOYUY2ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToYUY2Row = I422ToYUY2Row_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_NEON; @@ -220,14 +220,15 @@ int I420ToYUY2(const uint8* src_y, int src_stride_y, dst_stride_yuy2 = -dst_stride_yuy2; } #if defined(HAS_I422TOYUY2ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_SSE2; } } -#elif defined(HAS_I422TOYUY2ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOYUY2ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToYUY2Row = I422ToYUY2Row_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_NEON; @@ -280,14 +281,15 @@ int I422ToUYVY(const uint8* src_y, int src_stride_y, src_stride_y = src_stride_u = src_stride_v = dst_stride_uyvy = 0; } #if defined(HAS_I422TOUYVYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_SSE2; } } -#elif defined(HAS_I422TOUYVYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOUYVYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToUYVYRow = I422ToUYVYRow_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_NEON; @@ -326,14 +328,15 @@ int I420ToUYVY(const uint8* src_y, int src_stride_y, dst_stride_uyvy = -dst_stride_uyvy; } #if defined(HAS_I422TOUYVYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_SSE2; } } -#elif defined(HAS_I422TOUYVYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOUYVYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToUYVYRow = I422ToUYVYRow_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_NEON; @@ -397,20 +400,15 @@ int I420ToNV12(const uint8* src_y, int src_stride_y, src_stride_u = src_stride_v = dst_stride_uv = 0; } #if defined(HAS_MERGEUVROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow_ = MergeUVRow_Any_SSE2; if (IS_ALIGNED(halfwidth, 16)) { - MergeUVRow_ = MergeUVRow_Unaligned_SSE2; - if (IS_ALIGNED(src_u, 16) && IS_ALIGNED(src_stride_u, 16) && - IS_ALIGNED(src_v, 16) && IS_ALIGNED(src_stride_v, 16) && - IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { - MergeUVRow_ = MergeUVRow_SSE2; - } + MergeUVRow_ = MergeUVRow_SSE2; } } #endif #if defined(HAS_MERGEUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { MergeUVRow_ = MergeUVRow_Any_AVX2; if (IS_ALIGNED(halfwidth, 32)) { MergeUVRow_ = MergeUVRow_AVX2; @@ -418,7 +416,7 @@ int I420ToNV12(const uint8* src_y, int src_stride_y, } #endif #if defined(HAS_MERGEUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { MergeUVRow_ = MergeUVRow_Any_NEON; if (IS_ALIGNED(halfwidth, 16)) { MergeUVRow_ = MergeUVRow_NEON; @@ -452,185 +450,67 @@ int I420ToNV21(const uint8* src_y, int src_stride_y, width, height); } -// Convert I420 to ARGB. -LIBYUV_API -int I420ToARGB(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_argb, int dst_stride_argb, - int width, int height) { +// Convert I422 to RGBA with matrix +static int I420ToRGBAMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_rgba, int dst_stride_rgba, + const struct YuvConstants* yuvconstants, + int width, int height) { int y; - void (*I422ToARGBRow)(const uint8* y_buf, + void (*I422ToRGBARow)(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, - int width) = I422ToARGBRow_C; - if (!src_y || !src_u || !src_v || !dst_argb || + const struct YuvConstants* yuvconstants, + int width) = I422ToRGBARow_C; + if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; - dst_argb = dst_argb + (height - 1) * dst_stride_argb; - dst_stride_argb = -dst_stride_argb; + dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; + dst_stride_rgba = -dst_stride_rgba; } -#if defined(HAS_I422TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToARGBRow = I422ToARGBRow_Any_SSSE3; +#if defined(HAS_I422TORGBAROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToRGBARow = I422ToRGBARow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I422ToARGBRow = I422ToARGBRow_SSSE3; - } + I422ToRGBARow = I422ToRGBARow_SSSE3; } } #endif -#if defined(HAS_I422TOARGBROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { - I422ToARGBRow = I422ToARGBRow_Any_AVX2; +#if defined(HAS_I422TORGBAROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToRGBARow = I422ToRGBARow_Any_AVX2; if (IS_ALIGNED(width, 16)) { - I422ToARGBRow = I422ToARGBRow_AVX2; + I422ToRGBARow = I422ToRGBARow_AVX2; } } #endif -#if defined(HAS_I422TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToARGBRow = I422ToARGBRow_Any_NEON; +#if defined(HAS_I422TORGBAROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToRGBARow = I422ToRGBARow_Any_NEON; if (IS_ALIGNED(width, 8)) { - I422ToARGBRow = I422ToARGBRow_NEON; + I422ToRGBARow = I422ToRGBARow_NEON; } } #endif -#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) +#if defined(HAS_I422TORGBAROW_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && - IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { - I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; + IS_ALIGNED(dst_rgba, 4) && IS_ALIGNED(dst_stride_rgba, 4)) { + I422ToRGBARow = I422ToRGBARow_MIPS_DSPR2; } #endif for (y = 0; y < height; ++y) { - I422ToARGBRow(src_y, src_u, src_v, dst_argb, width); - dst_argb += dst_stride_argb; - src_y += src_stride_y; - if (y & 1) { - src_u += src_stride_u; - src_v += src_stride_v; - } - } - return 0; -} - -// Convert I420 to BGRA. -LIBYUV_API -int I420ToBGRA(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_bgra, int dst_stride_bgra, - int width, int height) { - int y; - void (*I422ToBGRARow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToBGRARow_C; - if (!src_y || !src_u || !src_v || !dst_bgra || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra; - dst_stride_bgra = -dst_stride_bgra; - } -#if defined(HAS_I422TOBGRAROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToBGRARow = I422ToBGRARow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) { - I422ToBGRARow = I422ToBGRARow_SSSE3; - } - } - } -#elif defined(HAS_I422TOBGRAROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToBGRARow = I422ToBGRARow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I422ToBGRARow = I422ToBGRARow_NEON; - } - } -#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && - IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && - IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && - IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && - IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) { - I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2; - } -#endif - - for (y = 0; y < height; ++y) { - I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width); - dst_bgra += dst_stride_bgra; - src_y += src_stride_y; - if (y & 1) { - src_u += src_stride_u; - src_v += src_stride_v; - } - } - return 0; -} - -// Convert I420 to ABGR. -LIBYUV_API -int I420ToABGR(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_abgr, int dst_stride_abgr, - int width, int height) { - int y; - void (*I422ToABGRRow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToABGRRow_C; - if (!src_y || !src_u || !src_v || !dst_abgr || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr; - dst_stride_abgr = -dst_stride_abgr; - } -#if defined(HAS_I422TOABGRROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToABGRRow = I422ToABGRRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) { - I422ToABGRRow = I422ToABGRRow_SSSE3; - } - } - } -#elif defined(HAS_I422TOABGRROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToABGRRow = I422ToABGRRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I422ToABGRRow = I422ToABGRRow_NEON; - } - } -#endif - - for (y = 0; y < height; ++y) { - I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width); - dst_abgr += dst_stride_abgr; + I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width); + dst_rgba += dst_stride_rgba; src_y += src_stride_y; if (y & 1) { src_u += src_stride_u; @@ -647,44 +527,81 @@ int I420ToRGBA(const uint8* src_y, int src_stride_y, const uint8* src_v, int src_stride_v, uint8* dst_rgba, int dst_stride_rgba, int width, int height) { + return I420ToRGBAMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_rgba, dst_stride_rgba, + &kYuvI601Constants, + width, height); +} + +// Convert I420 to BGRA. +LIBYUV_API +int I420ToBGRA(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_bgra, int dst_stride_bgra, + int width, int height) { + return I420ToRGBAMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_bgra, dst_stride_bgra, + &kYvuI601Constants, // Use Yvu matrix + width, height); +} + +// Convert I420 to RGB24 with matrix +static int I420ToRGB24Matrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_rgb24, int dst_stride_rgb24, + const struct YuvConstants* yuvconstants, + int width, int height) { int y; - void (*I422ToRGBARow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToRGBARow_C; - if (!src_y || !src_u || !src_v || !dst_rgba || + void (*I422ToRGB24Row)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* rgb_buf, + const struct YuvConstants* yuvconstants, + int width) = I422ToRGB24Row_C; + if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; - dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; - dst_stride_rgba = -dst_stride_rgba; + dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24; + dst_stride_rgb24 = -dst_stride_rgb24; } -#if defined(HAS_I422TORGBAROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToRGBARow = I422ToRGBARow_Any_SSSE3; +#if defined(HAS_I422TORGB24ROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { - I422ToRGBARow = I422ToRGBARow_SSSE3; - } + I422ToRGB24Row = I422ToRGB24Row_SSSE3; } } -#elif defined(HAS_I422TORGBAROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToRGBARow = I422ToRGBARow_Any_NEON; +#endif +#if defined(HAS_I422TORGB24ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToRGB24Row = I422ToRGB24Row_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToRGB24Row = I422ToRGB24Row_AVX2; + } + } +#endif +#if defined(HAS_I422TORGB24ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToRGB24Row = I422ToRGB24Row_Any_NEON; if (IS_ALIGNED(width, 8)) { - I422ToRGBARow = I422ToRGBARow_NEON; + I422ToRGB24Row = I422ToRGB24Row_NEON; } } #endif for (y = 0; y < height; ++y) { - I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width); - dst_rgba += dst_stride_rgba; + I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width); + dst_rgb24 += dst_stride_rgb24; src_y += src_stride_y; if (y & 1) { src_u += src_stride_u; @@ -701,99 +618,27 @@ int I420ToRGB24(const uint8* src_y, int src_stride_y, const uint8* src_v, int src_stride_v, uint8* dst_rgb24, int dst_stride_rgb24, int width, int height) { - int y; - void (*I422ToRGB24Row)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToRGB24Row_C; - if (!src_y || !src_u || !src_v || !dst_rgb24 || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24; - dst_stride_rgb24 = -dst_stride_rgb24; - } -#if defined(HAS_I422TORGB24ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToRGB24Row = I422ToRGB24Row_SSSE3; - } - } -#elif defined(HAS_I422TORGB24ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToRGB24Row = I422ToRGB24Row_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I422ToRGB24Row = I422ToRGB24Row_NEON; - } - } -#endif - - for (y = 0; y < height; ++y) { - I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, width); - dst_rgb24 += dst_stride_rgb24; - src_y += src_stride_y; - if (y & 1) { - src_u += src_stride_u; - src_v += src_stride_v; - } - } - return 0; + return I420ToRGB24Matrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_rgb24, dst_stride_rgb24, + &kYuvI601Constants, + width, height); } // Convert I420 to RAW. LIBYUV_API int I420ToRAW(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_raw, int dst_stride_raw, - int width, int height) { - int y; - void (*I422ToRAWRow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToRAWRow_C; - if (!src_y || !src_u || !src_v || !dst_raw || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_raw = dst_raw + (height - 1) * dst_stride_raw; - dst_stride_raw = -dst_stride_raw; - } -#if defined(HAS_I422TORAWROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToRAWRow = I422ToRAWRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToRAWRow = I422ToRAWRow_SSSE3; - } - } -#elif defined(HAS_I422TORAWROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToRAWRow = I422ToRAWRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I422ToRAWRow = I422ToRAWRow_NEON; - } - } -#endif - - for (y = 0; y < height; ++y) { - I422ToRAWRow(src_y, src_u, src_v, dst_raw, width); - dst_raw += dst_stride_raw; - src_y += src_stride_y; - if (y & 1) { - src_u += src_stride_u; - src_v += src_stride_v; - } - } - return 0; + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_raw, int dst_stride_raw, + int width, int height) { + return I420ToRGB24Matrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_raw, dst_stride_raw, + &kYvuI601Constants, // Use Yvu matrix + width, height); } // Convert I420 to ARGB1555. @@ -808,6 +653,7 @@ int I420ToARGB1555(const uint8* src_y, int src_stride_y, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = I422ToARGB1555Row_C; if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 || height == 0) { @@ -820,14 +666,23 @@ int I420ToARGB1555(const uint8* src_y, int src_stride_y, dst_stride_argb1555 = -dst_stride_argb1555; } #if defined(HAS_I422TOARGB1555ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { I422ToARGB1555Row = I422ToARGB1555Row_SSSE3; } } -#elif defined(HAS_I422TOARGB1555ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_I422TOARGB1555ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGB1555Row = I422ToARGB1555Row_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGB1555ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON; if (IS_ALIGNED(width, 8)) { I422ToARGB1555Row = I422ToARGB1555Row_NEON; @@ -836,7 +691,8 @@ int I420ToARGB1555(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, width); + I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants, + width); dst_argb1555 += dst_stride_argb1555; src_y += src_stride_y; if (y & 1) { @@ -860,6 +716,7 @@ int I420ToARGB4444(const uint8* src_y, int src_stride_y, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = I422ToARGB4444Row_C; if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 || height == 0) { @@ -872,14 +729,23 @@ int I420ToARGB4444(const uint8* src_y, int src_stride_y, dst_stride_argb4444 = -dst_stride_argb4444; } #if defined(HAS_I422TOARGB4444ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { I422ToARGB4444Row = I422ToARGB4444Row_SSSE3; } } -#elif defined(HAS_I422TOARGB4444ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_I422TOARGB4444ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGB4444Row = I422ToARGB4444Row_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGB4444ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON; if (IS_ALIGNED(width, 8)) { I422ToARGB4444Row = I422ToARGB4444Row_NEON; @@ -888,7 +754,8 @@ int I420ToARGB4444(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, width); + I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants, + width); dst_argb4444 += dst_stride_argb4444; src_y += src_stride_y; if (y & 1) { @@ -911,6 +778,7 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = I422ToRGB565Row_C; if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) { @@ -923,14 +791,23 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, dst_stride_rgb565 = -dst_stride_rgb565; } #if defined(HAS_I422TORGB565ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { I422ToRGB565Row = I422ToRGB565Row_SSSE3; } } -#elif defined(HAS_I422TORGB565ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_I422TORGB565ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToRGB565Row = I422ToRGB565Row_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToRGB565Row = I422ToRGB565Row_AVX2; + } + } +#endif +#if defined(HAS_I422TORGB565ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToRGB565Row = I422ToRGB565Row_Any_NEON; if (IS_ALIGNED(width, 8)) { I422ToRGB565Row = I422ToRGB565Row_NEON; @@ -939,7 +816,7 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, width); + I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, &kYuvI601Constants, width); dst_rgb565 += dst_stride_rgb565; src_y += src_stride_y; if (y & 1) { @@ -950,6 +827,118 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, return 0; } +// Ordered 8x8 dither for 888 to 565. Values from 0 to 7. +static const uint8 kDither565_4x4[16] = { + 0, 4, 1, 5, + 6, 2, 7, 3, + 1, 5, 0, 4, + 7, 3, 6, 2, +}; + +// Convert I420 to RGB565 with dithering. +LIBYUV_API +int I420ToRGB565Dither(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_rgb565, int dst_stride_rgb565, + const uint8* dither4x4, int width, int height) { + int y; + void (*I422ToARGBRow)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* rgb_buf, + const struct YuvConstants* yuvconstants, + int width) = I422ToARGBRow_C; + void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) = ARGBToRGB565DitherRow_C; + if (!src_y || !src_u || !src_v || !dst_rgb565 || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; + dst_stride_rgb565 = -dst_stride_rgb565; + } + if (!dither4x4) { + dither4x4 = kDither565_4x4; + } +#if defined(HAS_I422TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToARGBRow = I422ToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_SSSE3; + } + } +#endif +#if defined(HAS_I422TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToARGBRow = I422ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGBRow = I422ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToARGBRow = I422ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_NEON; + } + } +#endif +#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2)) { + I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; + } +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2; + if (IS_ALIGNED(width, 4)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2; + } + } +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON; + } + } +#endif + { + // Allocate a row of argb. + align_buffer_64(row_argb, width * 4); + for (y = 0; y < height; ++y) { + I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width); + ARGBToRGB565DitherRow(row_argb, dst_rgb565, + *(uint32*)(dither4x4 + ((y & 3) << 2)), width); + dst_rgb565 += dst_stride_rgb565; + src_y += src_stride_y; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } + } + free_aligned_buffer_64(row_argb); + } + return 0; +} + // Convert I420 to specified format LIBYUV_API int ConvertFromI420(const uint8* y, int y_stride, @@ -1054,38 +1043,6 @@ int ConvertFromI420(const uint8* y, int y_stride, dst_sample_stride ? dst_sample_stride : width * 4, width, height); break; - case FOURCC_BGGR: - r = I420ToBayerBGGR(y, y_stride, - u, u_stride, - v, v_stride, - dst_sample, - dst_sample_stride ? dst_sample_stride : width, - width, height); - break; - case FOURCC_GBRG: - r = I420ToBayerGBRG(y, y_stride, - u, u_stride, - v, v_stride, - dst_sample, - dst_sample_stride ? dst_sample_stride : width, - width, height); - break; - case FOURCC_GRBG: - r = I420ToBayerGRBG(y, y_stride, - u, u_stride, - v, v_stride, - dst_sample, - dst_sample_stride ? dst_sample_stride : width, - width, height); - break; - case FOURCC_RGGB: - r = I420ToBayerRGGB(y, y_stride, - u, u_stride, - v, v_stride, - dst_sample, - dst_sample_stride ? dst_sample_stride : width, - width, height); - break; case FOURCC_I400: r = I400Copy(y, y_stride, dst_sample, @@ -1116,7 +1073,7 @@ int ConvertFromI420(const uint8* y, int y_stride, width, height); break; } - // TODO(fbarchard): Add M420 and Q420. + // TODO(fbarchard): Add M420. // Triplanar formats // TODO(fbarchard): halfstride instead of halfwidth case FOURCC_I420: diff --git a/TMessagesProj/jni/libyuv/source/convert_from_argb.cc b/TMessagesProj/jni/libyuv/source/convert_from_argb.cc index de461ddb..6796343c 100644 --- a/TMessagesProj/jni/libyuv/source/convert_from_argb.cc +++ b/TMessagesProj/jni/libyuv/source/convert_from_argb.cc @@ -12,7 +12,6 @@ #include "libyuv/basic_types.h" #include "libyuv/cpu_id.h" -#include "libyuv/format_conversion.h" #include "libyuv/planar_functions.h" #include "libyuv/row.h" @@ -29,10 +28,10 @@ int ARGBToI444(const uint8* src_argb, int src_stride_argb, uint8* dst_v, int dst_stride_v, int width, int height) { int y; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) = ARGBToUV444Row_C; + int width) = ARGBToUV444Row_C; if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { return -1; } @@ -51,17 +50,15 @@ int ARGBToI444(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_ARGBTOUV444ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUV444Row = ARGBToUV444Row_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUV444Row = ARGBToUV444Row_SSSE3; - } + ARGBToUV444Row = ARGBToUV444Row_SSSE3; } } -#elif defined(HAS_ARGBTOUV444ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOUV444ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUV444Row = ARGBToUV444Row_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToUV444Row = ARGBToUV444Row_NEON; @@ -69,19 +66,23 @@ int ARGBToI444(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } - -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -109,8 +110,8 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb, int width, int height) { int y; void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) = ARGBToUV422Row_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + int width) = ARGBToUV422Row_C; + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { return -1; @@ -130,37 +131,39 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_ARGBTOUV422ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUV422Row = ARGBToUV422Row_SSSE3; - } + ARGBToUV422Row = ARGBToUV422Row_SSSE3; } } -#elif defined(HAS_ARGBTOUV422ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_ARGBTOUV422ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUV422Row = ARGBToUV422Row_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUV422Row = ARGBToUV422Row_NEON; } } #endif - #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -188,8 +191,8 @@ int ARGBToI411(const uint8* src_argb, int src_stride_argb, int width, int height) { int y; void (*ARGBToUV411Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) = ARGBToUV411Row_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + int width) = ARGBToUV411Row_C; + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { return -1; @@ -209,19 +212,15 @@ int ARGBToI411(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } #endif #if defined(HAS_ARGBTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBToYRow = ARGBToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { ARGBToYRow = ARGBToYRow_AVX2; @@ -229,7 +228,7 @@ int ARGBToI411(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -237,7 +236,7 @@ int ARGBToI411(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOUV411ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 32) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUV411Row = ARGBToUV411Row_Any_NEON; if (IS_ALIGNED(width, 32)) { ARGBToUV411Row = ARGBToUV411Row_NEON; @@ -265,7 +264,7 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, int halfwidth = (width + 1) >> 1; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) = MergeUVRow_C; @@ -281,22 +280,27 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, src_stride_argb = -src_stride_argb; } #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -304,7 +308,7 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUVRow = ARGBToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUVRow = ARGBToUVRow_NEON; @@ -312,18 +316,15 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_MERGEUVROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow_ = MergeUVRow_Any_SSE2; if (IS_ALIGNED(halfwidth, 16)) { - MergeUVRow_ = MergeUVRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { - MergeUVRow_ = MergeUVRow_SSE2; - } + MergeUVRow_ = MergeUVRow_SSE2; } } #endif #if defined(HAS_MERGEUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { MergeUVRow_ = MergeUVRow_Any_AVX2; if (IS_ALIGNED(halfwidth, 32)) { MergeUVRow_ = MergeUVRow_AVX2; @@ -331,7 +332,7 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_MERGEUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { MergeUVRow_ = MergeUVRow_Any_NEON; if (IS_ALIGNED(halfwidth, 16)) { MergeUVRow_ = MergeUVRow_NEON; @@ -340,8 +341,8 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, #endif { // Allocate a rows of uv. - align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2); - uint8* row_v = row_u + ((halfwidth + 15) & ~15); + align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2); + uint8* row_v = row_u + ((halfwidth + 31) & ~31); for (y = 0; y < height - 1; y += 2) { ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); @@ -372,7 +373,7 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, int halfwidth = (width + 1) >> 1; void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) = MergeUVRow_C; @@ -388,22 +389,27 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, src_stride_argb = -src_stride_argb; } #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } + ARGBToUVRow = ARGBToUVRow_SSSE3; + ARGBToYRow = ARGBToYRow_SSSE3; } } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToUVRow = ARGBToUVRow_Any_AVX2; + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_AVX2; + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -411,7 +417,7 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUVRow = ARGBToUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUVRow = ARGBToUVRow_NEON; @@ -419,18 +425,15 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_MERGEUVROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow_ = MergeUVRow_Any_SSE2; if (IS_ALIGNED(halfwidth, 16)) { - MergeUVRow_ = MergeUVRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { - MergeUVRow_ = MergeUVRow_SSE2; - } + MergeUVRow_ = MergeUVRow_SSE2; } } #endif #if defined(HAS_MERGEUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { MergeUVRow_ = MergeUVRow_Any_AVX2; if (IS_ALIGNED(halfwidth, 32)) { MergeUVRow_ = MergeUVRow_AVX2; @@ -438,7 +441,7 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_MERGEUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { MergeUVRow_ = MergeUVRow_Any_NEON; if (IS_ALIGNED(halfwidth, 16)) { MergeUVRow_ = MergeUVRow_NEON; @@ -447,8 +450,8 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, #endif { // Allocate a rows of uv. - align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2); - uint8* row_v = row_u + ((halfwidth + 15) & ~15); + align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2); + uint8* row_v = row_u + ((halfwidth + 31) & ~31); for (y = 0; y < height - 1; y += 2) { ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); @@ -476,8 +479,8 @@ int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, int width, int height) { int y; void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) = ARGBToUV422Row_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + int width) = ARGBToUV422Row_C; + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_yuy2, int width) = I422ToYUY2Row_C; @@ -500,17 +503,15 @@ int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_yuy2 = 0; } #if defined(HAS_ARGBTOUV422ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUV422Row = ARGBToUV422Row_SSSE3; - } + ARGBToUV422Row = ARGBToUV422Row_SSSE3; } } -#elif defined(HAS_ARGBTOUV422ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_ARGBTOUV422ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUV422Row = ARGBToUV422Row_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUV422Row = ARGBToUV422Row_NEON; @@ -518,17 +519,23 @@ int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -537,14 +544,15 @@ int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, #endif #if defined(HAS_I422TOYUY2ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_SSE2; } } -#elif defined(HAS_I422TOYUY2ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOYUY2ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToYUY2Row = I422ToYUY2Row_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToYUY2Row = I422ToYUY2Row_NEON; @@ -578,8 +586,8 @@ int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, int width, int height) { int y; void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) = ARGBToUV422Row_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + int width) = ARGBToUV422Row_C; + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_uyvy, int width) = I422ToUYVYRow_C; @@ -602,17 +610,15 @@ int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_uyvy = 0; } #if defined(HAS_ARGBTOUV422ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUV422Row = ARGBToUV422Row_SSSE3; - } + ARGBToUV422Row = ARGBToUV422Row_SSSE3; } } -#elif defined(HAS_ARGBTOUV422ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_ARGBTOUV422ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUV422Row = ARGBToUV422Row_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUV422Row = ARGBToUV422Row_NEON; @@ -620,17 +626,23 @@ int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOYROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYRow = ARGBToYRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYRow = ARGBToYRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -639,14 +651,15 @@ int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, #endif #if defined(HAS_I422TOUYVYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_SSE2; } } -#elif defined(HAS_I422TOUYVYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { +#endif +#if defined(HAS_I422TOUYVYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { I422ToUYVYRow = I422ToUYVYRow_Any_NEON; if (IS_ALIGNED(width, 16)) { I422ToUYVYRow = I422ToUYVYRow_NEON; @@ -679,7 +692,7 @@ int ARGBToI400(const uint8* src_argb, int src_stride_argb, uint8* dst_y, int dst_stride_y, int width, int height) { int y; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int width) = ARGBToYRow_C; if (!src_argb || !dst_y || width <= 0 || height == 0) { return -1; @@ -697,19 +710,15 @@ int ARGBToI400(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_y = 0; } #if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYRow = ARGBToYRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } + ARGBToYRow = ARGBToYRow_SSSE3; } } #endif #if defined(HAS_ARGBTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBToYRow = ARGBToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { ARGBToYRow = ARGBToYRow_AVX2; @@ -717,7 +726,7 @@ int ARGBToI400(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYRow = ARGBToYRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYRow = ARGBToYRow_NEON; @@ -755,7 +764,7 @@ int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, uint8* dst_rgb24, int dst_stride_rgb24, int width, int height) { int y; - void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = + void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int width) = ARGBToRGB24Row_C; if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) { return -1; @@ -773,14 +782,15 @@ int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_rgb24 = 0; } #if defined(HAS_ARGBTORGB24ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { ARGBToRGB24Row = ARGBToRGB24Row_SSSE3; } } -#elif defined(HAS_ARGBTORGB24ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTORGB24ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToRGB24Row = ARGBToRGB24Row_NEON; @@ -802,7 +812,7 @@ int ARGBToRAW(const uint8* src_argb, int src_stride_argb, uint8* dst_raw, int dst_stride_raw, int width, int height) { int y; - void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int pix) = + void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int width) = ARGBToRAWRow_C; if (!src_argb || !dst_raw || width <= 0 || height == 0) { return -1; @@ -820,14 +830,15 @@ int ARGBToRAW(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_raw = 0; } #if defined(HAS_ARGBTORAWROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { ARGBToRAWRow = ARGBToRAWRow_SSSE3; } } -#elif defined(HAS_ARGBTORAWROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTORAWROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToRAWRow = ARGBToRAWRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToRAWRow = ARGBToRAWRow_NEON; @@ -843,13 +854,74 @@ int ARGBToRAW(const uint8* src_argb, int src_stride_argb, return 0; } +// Ordered 8x8 dither for 888 to 565. Values from 0 to 7. +static const uint8 kDither565_4x4[16] = { + 0, 4, 1, 5, + 6, 2, 7, 3, + 1, 5, 0, 4, + 7, 3, 6, 2, +}; + +// Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). +LIBYUV_API +int ARGBToRGB565Dither(const uint8* src_argb, int src_stride_argb, + uint8* dst_rgb565, int dst_stride_rgb565, + const uint8* dither4x4, int width, int height) { + int y; + void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) = ARGBToRGB565DitherRow_C; + if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) { + return -1; + } + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + if (!dither4x4) { + dither4x4 = kDither565_4x4; + } +#if defined(HAS_ARGBTORGB565DITHERROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2; + if (IS_ALIGNED(width, 4)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2; + } + } +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON; + } + } +#endif + for (y = 0; y < height; ++y) { + ARGBToRGB565DitherRow(src_argb, dst_rgb565, + *(uint32*)(dither4x4 + ((y & 3) << 2)), width); + src_argb += src_stride_argb; + dst_rgb565 += dst_stride_rgb565; + } + return 0; +} + // Convert ARGB To RGB565. +// TODO(fbarchard): Consider using dither function low level with zeros. LIBYUV_API int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, uint8* dst_rgb565, int dst_stride_rgb565, int width, int height) { int y; - void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = + void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int width) = ARGBToRGB565Row_C; if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) { return -1; @@ -867,15 +939,23 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_rgb565 = 0; } #if defined(HAS_ARGBTORGB565ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBToRGB565Row = ARGBToRGB565Row_SSE2; } } -#elif defined(HAS_ARGBTORGB565ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTORGB565ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToRGB565Row = ARGBToRGB565Row_AVX2; + } + } +#endif +#if defined(HAS_ARGBTORGB565ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToRGB565Row = ARGBToRGB565Row_NEON; @@ -897,7 +977,7 @@ int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, uint8* dst_argb1555, int dst_stride_argb1555, int width, int height) { int y; - void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = + void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int width) = ARGBToARGB1555Row_C; if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) { return -1; @@ -915,15 +995,23 @@ int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb1555 = 0; } #if defined(HAS_ARGBTOARGB1555ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2; } } -#elif defined(HAS_ARGBTOARGB1555ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOARGB1555ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOARGB1555ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToARGB1555Row = ARGBToARGB1555Row_NEON; @@ -945,7 +1033,7 @@ int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, uint8* dst_argb4444, int dst_stride_argb4444, int width, int height) { int y; - void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = + void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int width) = ARGBToARGB4444Row_C; if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) { return -1; @@ -963,15 +1051,23 @@ int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb4444 = 0; } #if defined(HAS_ARGBTOARGB4444ROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2; } } -#elif defined(HAS_ARGBTOARGB4444ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_ARGBTOARGB4444ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOARGB4444ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToARGB4444Row = ARGBToARGB4444Row_NEON; @@ -996,8 +1092,8 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, int width, int height) { int y; void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C; - void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = + uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C; + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int width) = ARGBToYJRow_C; if (!src_argb || !dst_yj || !dst_u || !dst_v || @@ -1011,23 +1107,17 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, src_stride_argb = -src_stride_argb; } #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3; ARGBToYJRow = ARGBToYJRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToUVJRow = ARGBToUVJRow_Unaligned_SSSE3; - ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToUVJRow = ARGBToUVJRow_SSSE3; - if (IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { - ARGBToYJRow = ARGBToYJRow_SSSE3; - } - } + ARGBToUVJRow = ARGBToUVJRow_SSSE3; + ARGBToYJRow = ARGBToYJRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOYJROW_AVX2) && defined(HAS_ARGBTOUVJROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { +#if defined(HAS_ARGBTOYJROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { ARGBToYJRow = ARGBToYJRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { ARGBToYJRow = ARGBToYJRow_AVX2; @@ -1035,7 +1125,7 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYJROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYJRow = ARGBToYJRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYJRow = ARGBToYJRow_NEON; @@ -1043,7 +1133,7 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOUVJROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToUVJRow = ARGBToUVJRow_Any_NEON; if (IS_ALIGNED(width, 16)) { ARGBToUVJRow = ARGBToUVJRow_NEON; @@ -1067,13 +1157,95 @@ int ARGBToJ420(const uint8* src_argb, int src_stride_argb, return 0; } +// ARGB little endian (bgra in memory) to J422 +LIBYUV_API +int ARGBToJ422(const uint8* src_argb, int src_stride_argb, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height) { + int y; + void (*ARGBToUVJ422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, + int width) = ARGBToUVJ422Row_C; + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_y, int width) = + ARGBToYJRow_C; + if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { + return -1; + } + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + // Coalesce rows. + if (src_stride_argb == width * 4 && + dst_stride_y == width && + dst_stride_u * 2 == width && + dst_stride_v * 2 == width) { + width *= height; + height = 1; + src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; + } +#if defined(HAS_ARGBTOUVJ422ROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToUVJ422Row = ARGBToUVJ422Row_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + ARGBToUVJ422Row = ARGBToUVJ422Row_SSSE3; + } + } +#endif +#if defined(HAS_ARGBTOUVJ422ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBToUVJ422Row = ARGBToUVJ422Row_Any_NEON; + if (IS_ALIGNED(width, 16)) { + ARGBToUVJ422Row = ARGBToUVJ422Row_NEON; + } + } +#endif + +#if defined(HAS_ARGBTOYJROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + ARGBToYJRow = ARGBToYJRow_SSSE3; + } + } +#endif +#if defined(HAS_ARGBTOYJROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYJRow = ARGBToYJRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYJRow = ARGBToYJRow_AVX2; + } + } +#endif +#if defined(HAS_ARGBTOYJROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBToYJRow = ARGBToYJRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBToYJRow = ARGBToYJRow_NEON; + } + } +#endif + + for (y = 0; y < height; ++y) { + ARGBToUVJ422Row(src_argb, dst_u, dst_v, width); + ARGBToYJRow(src_argb, dst_y, width); + src_argb += src_stride_argb; + dst_y += dst_stride_y; + dst_u += dst_stride_u; + dst_v += dst_stride_v; + } + return 0; +} + // Convert ARGB to J400. LIBYUV_API int ARGBToJ400(const uint8* src_argb, int src_stride_argb, uint8* dst_yj, int dst_stride_yj, int width, int height) { int y; - void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int width) = ARGBToYJRow_C; if (!src_argb || !dst_yj || width <= 0 || height == 0) { return -1; @@ -1091,19 +1263,15 @@ int ARGBToJ400(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_yj = 0; } #if defined(HAS_ARGBTOYJROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToYJRow = ARGBToYJRow_Any_SSSE3; if (IS_ALIGNED(width, 16)) { - ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { - ARGBToYJRow = ARGBToYJRow_SSSE3; - } + ARGBToYJRow = ARGBToYJRow_SSSE3; } } #endif #if defined(HAS_ARGBTOYJROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBToYJRow = ARGBToYJRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { ARGBToYJRow = ARGBToYJRow_AVX2; @@ -1111,7 +1279,7 @@ int ARGBToJ400(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBTOYJROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBToYJRow = ARGBToYJRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBToYJRow = ARGBToYJRow_NEON; diff --git a/TMessagesProj/jni/libyuv/source/convert_to_argb.cc b/TMessagesProj/jni/libyuv/source/convert_to_argb.cc index 1b228a7b..af829fbd 100644 --- a/TMessagesProj/jni/libyuv/source/convert_to_argb.cc +++ b/TMessagesProj/jni/libyuv/source/convert_to_argb.cc @@ -11,7 +11,6 @@ #include "libyuv/convert_argb.h" #include "libyuv/cpu_id.h" -#include "libyuv/format_conversion.h" #ifdef HAVE_JPEG #include "libyuv/mjpeg_decoder.h" #endif @@ -144,36 +143,6 @@ int ConvertToARGB(const uint8* sample, size_t sample_size, crop_argb, argb_stride, crop_width, inv_crop_height); break; - // TODO(fbarchard): Support cropping Bayer by odd numbers - // by adjusting fourcc. - case FOURCC_BGGR: - src = sample + (src_width * crop_y + crop_x); - r = BayerBGGRToARGB(src, src_width, - crop_argb, argb_stride, - crop_width, inv_crop_height); - break; - - case FOURCC_GBRG: - src = sample + (src_width * crop_y + crop_x); - r = BayerGBRGToARGB(src, src_width, - crop_argb, argb_stride, - crop_width, inv_crop_height); - break; - - case FOURCC_GRBG: - src = sample + (src_width * crop_y + crop_x); - r = BayerGRBGToARGB(src, src_width, - crop_argb, argb_stride, - crop_width, inv_crop_height); - break; - - case FOURCC_RGGB: - src = sample + (src_width * crop_y + crop_x); - r = BayerRGGBToARGB(src, src_width, - crop_argb, argb_stride, - crop_width, inv_crop_height); - break; - case FOURCC_I400: src = sample + src_width * crop_y + crop_x; r = I400ToARGB(src, src_width, @@ -205,15 +174,6 @@ int ConvertToARGB(const uint8* sample, size_t sample_size, crop_argb, argb_stride, crop_width, inv_crop_height); break; -// case FOURCC_Q420: -// src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x; -// src_uv = sample + (src_width + aligned_src_width * 2) * crop_y + -// src_width + crop_x * 2; -// r = Q420ToARGB(src, src_width * 3, -// src_uv, src_width * 3, -// crop_argb, argb_stride, -// crop_width, inv_crop_height); -// break; // Triplanar formats case FOURCC_I420: case FOURCC_YU12: @@ -241,6 +201,25 @@ int ConvertToARGB(const uint8* sample, size_t sample_size, crop_width, inv_crop_height); break; } + + case FOURCC_J420: { + const uint8* src_y = sample + (src_width * crop_y + crop_x); + const uint8* src_u; + const uint8* src_v; + int halfwidth = (src_width + 1) / 2; + int halfheight = (abs_src_height + 1) / 2; + src_u = sample + src_width * abs_src_height + + (halfwidth * crop_y + crop_x) / 2; + src_v = sample + src_width * abs_src_height + + halfwidth * (halfheight + crop_y / 2) + crop_x / 2; + r = J420ToARGB(src_y, src_width, + src_u, halfwidth, + src_v, halfwidth, + crop_argb, argb_stride, + crop_width, inv_crop_height); + break; + } + case FOURCC_I422: case FOURCC_YV16: { const uint8* src_y = sample + src_width * crop_y + crop_x; diff --git a/TMessagesProj/jni/libyuv/source/convert_to_i420.cc b/TMessagesProj/jni/libyuv/source/convert_to_i420.cc index 7b194fff..5e75369b 100644 --- a/TMessagesProj/jni/libyuv/source/convert_to_i420.cc +++ b/TMessagesProj/jni/libyuv/source/convert_to_i420.cc @@ -12,7 +12,6 @@ #include "libyuv/convert.h" -#include "libyuv/format_conversion.h" #include "libyuv/video_common.h" #ifdef __cplusplus @@ -173,40 +172,6 @@ int ConvertToI420(const uint8* sample, v, v_stride, crop_width, inv_crop_height); break; - // TODO(fbarchard): Support cropping Bayer by odd numbers - // by adjusting fourcc. - case FOURCC_BGGR: - src = sample + (src_width * crop_y + crop_x); - r = BayerBGGRToI420(src, src_width, - y, y_stride, - u, u_stride, - v, v_stride, - crop_width, inv_crop_height); - break; - case FOURCC_GBRG: - src = sample + (src_width * crop_y + crop_x); - r = BayerGBRGToI420(src, src_width, - y, y_stride, - u, u_stride, - v, v_stride, - crop_width, inv_crop_height); - break; - case FOURCC_GRBG: - src = sample + (src_width * crop_y + crop_x); - r = BayerGRBGToI420(src, src_width, - y, y_stride, - u, u_stride, - v, v_stride, - crop_width, inv_crop_height); - break; - case FOURCC_RGGB: - src = sample + (src_width * crop_y + crop_x); - r = BayerRGGBToI420(src, src_width, - y, y_stride, - u, u_stride, - v, v_stride, - crop_width, inv_crop_height); - break; case FOURCC_I400: src = sample + src_width * crop_y + crop_x; r = I400ToI420(src, src_width, @@ -218,7 +183,8 @@ int ConvertToI420(const uint8* sample, // Biplanar formats case FOURCC_NV12: src = sample + (src_width * crop_y + crop_x); - src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x; + src_uv = sample + (src_width * src_height) + + ((crop_y / 2) * aligned_src_width) + ((crop_x / 2) * 2); r = NV12ToI420Rotate(src, src_width, src_uv, aligned_src_width, y, y_stride, @@ -228,7 +194,8 @@ int ConvertToI420(const uint8* sample, break; case FOURCC_NV21: src = sample + (src_width * crop_y + crop_x); - src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x; + src_uv = sample + (src_width * src_height) + + ((crop_y / 2) * aligned_src_width) + ((crop_x / 2) * 2); // Call NV12 but with u and v parameters swapped. r = NV12ToI420Rotate(src, src_width, src_uv, aligned_src_width, @@ -245,17 +212,6 @@ int ConvertToI420(const uint8* sample, v, v_stride, crop_width, inv_crop_height); break; - case FOURCC_Q420: - src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x; - src_uv = sample + (src_width + aligned_src_width * 2) * crop_y + - src_width + crop_x * 2; - r = Q420ToI420(src, src_width * 3, - src_uv, src_width * 3, - y, y_stride, - u, u_stride, - v, v_stride, - crop_width, inv_crop_height); - break; // Triplanar formats case FOURCC_I420: case FOURCC_YU12: diff --git a/TMessagesProj/jni/libyuv/source/cpu_id.cc b/TMessagesProj/jni/libyuv/source/cpu_id.cc index deb4c446..ff7bdbd9 100644 --- a/TMessagesProj/jni/libyuv/source/cpu_id.cc +++ b/TMessagesProj/jni/libyuv/source/cpu_id.cc @@ -14,8 +14,8 @@ #include // For __cpuidex() #endif #if !defined(__pnacl__) && !defined(__CLR_VER) && \ - !defined(__native_client__) && \ - defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219) + !defined(__native_client__) && (defined(_M_IX86) || defined(_M_X64)) && \ + defined(_MSC_VER) && !defined(__clang__) && (_MSC_FULL_VER >= 160040219) #include // For _xgetbv() #endif @@ -36,19 +36,20 @@ extern "C" { // For functions that use the stack and have runtime checks for overflow, // use SAFEBUFFERS to avoid additional check. -#if defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219) +#if (defined(_MSC_VER) && !defined(__clang__)) && (_MSC_FULL_VER >= 160040219) #define SAFEBUFFERS __declspec(safebuffers) #else #define SAFEBUFFERS #endif -// Low level cpuid for X86. Returns zeros on other CPUs. -#if !defined(__pnacl__) && !defined(__CLR_VER) && \ - (defined(_M_IX86) || defined(_M_X64) || \ - defined(__i386__) || defined(__x86_64__)) +// Low level cpuid for X86. +#if (defined(_M_IX86) || defined(_M_X64) || \ + defined(__i386__) || defined(__x86_64__)) && \ + !defined(__pnacl__) && !defined(__CLR_VER) LIBYUV_API void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { #if defined(_MSC_VER) && !defined(__clang__) +// Visual C version uses intrinsic or inline x86 assembly. #if (_MSC_FULL_VER >= 160040219) __cpuidex((int*)(cpu_info), info_eax, info_ecx); #elif defined(_M_IX86) @@ -62,16 +63,17 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { mov [edi + 8], ecx mov [edi + 12], edx } -#else +#else // Visual C but not x86 if (info_ecx == 0) { __cpuid((int*)(cpu_info), info_eax); } else { cpu_info[3] = cpu_info[2] = cpu_info[1] = cpu_info[0] = 0; } #endif -#else // defined(_MSC_VER) +// GCC version uses inline x86 assembly. +#else // defined(_MSC_VER) && !defined(__clang__) uint32 info_ebx, info_edx; - asm volatile ( // NOLINT + asm volatile ( #if defined( __i386__) && defined(__PIC__) // Preserve ebx for fpic 32 bit. "mov %%ebx, %%edi \n" @@ -87,35 +89,47 @@ void CpuId(uint32 info_eax, uint32 info_ecx, uint32* cpu_info) { cpu_info[1] = info_ebx; cpu_info[2] = info_ecx; cpu_info[3] = info_edx; -#endif // defined(_MSC_VER) +#endif // defined(_MSC_VER) && !defined(__clang__) } - -#if !defined(__native_client__) -#define HAS_XGETBV -// X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. -int TestOsSaveYmm() { - uint32 xcr0 = 0u; -#if defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219) - xcr0 = (uint32)(_xgetbv(0)); // VS2010 SP1 required. -#elif defined(_M_IX86) && defined(_MSC_VER) - __asm { - xor ecx, ecx // xcr 0 - _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 // For VS2010 and earlier. - mov xcr0, eax - } -#elif defined(__i386__) || defined(__x86_64__) - asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcr0) : "c" (0) : "%edx"); -#endif // defined(_MSC_VER) - return((xcr0 & 6) == 6); // Is ymm saved? -} -#endif // !defined(__native_client__) -#else +#else // (defined(_M_IX86) || defined(_M_X64) ... LIBYUV_API void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info) { cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; } #endif +// For VS2010 and earlier emit can be used: +// _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 // For VS2010 and earlier. +// __asm { +// xor ecx, ecx // xcr 0 +// xgetbv +// mov xcr0, eax +// } +// For VS2013 and earlier 32 bit, the _xgetbv(0) optimizer produces bad code. +// https://code.google.com/p/libyuv/issues/detail?id=529 +#if defined(_M_IX86) && (_MSC_VER < 1900) +#pragma optimize("g", off) +#endif +#if (defined(_M_IX86) || defined(_M_X64) || \ + defined(__i386__) || defined(__x86_64__)) && \ + !defined(__pnacl__) && !defined(__CLR_VER) && !defined(__native_client__) +#define HAS_XGETBV +// X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. +int GetXCR0() { + uint32 xcr0 = 0u; +#if (_MSC_FULL_VER >= 160040219) + xcr0 = (uint32)(_xgetbv(0)); // VS2010 SP1 required. +#elif defined(__i386__) || defined(__x86_64__) + asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcr0) : "c" (0) : "%edx"); +#endif // defined(__i386__) || defined(__x86_64__) + return xcr0; +} +#endif // defined(_M_IX86) || defined(_M_X64) .. +// Return optimization to previous setting. +#if defined(_M_IX86) && (_MSC_VER < 1900) +#pragma optimize("g", on) +#endif + // based on libvpx arm_cpudetect.c // For Arm, but public to allow testing on any CPU LIBYUV_API SAFEBUFFERS @@ -134,36 +148,21 @@ int ArmCpuCaps(const char* cpuinfo_name) { fclose(f); return kCpuHasNEON; } + // aarch64 uses asimd for Neon. + p = strstr(cpuinfo_line, " asimd"); + if (p && (p[6] == ' ' || p[6] == '\n')) { + fclose(f); + return kCpuHasNEON; + } } } fclose(f); return 0; } -#if defined(__mips__) && defined(__linux__) -static int MipsCpuCaps(const char* search_string) { - char cpuinfo_line[512]; - const char* file_name = "/proc/cpuinfo"; - FILE* f = fopen(file_name, "r"); - if (!f) { - // Assume DSP if /proc/cpuinfo is unavailable. - // This will occur for Chrome sandbox for Pepper or Render process. - return kCpuHasMIPS_DSP; - } - while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f) != NULL) { - if (strstr(cpuinfo_line, search_string) != NULL) { - fclose(f); - return kCpuHasMIPS_DSP; - } - } - fclose(f); - return 0; -} -#endif - // CPU detect function for SIMD instruction sets. LIBYUV_API -int cpu_info_ = kCpuInit; // cpu_info is not initialized yet. +int cpu_info_ = 0; // cpu_info is not initialized yet. // Test environment variable for disabling CPU features. Any non-zero value // to disable. Zero ignored to make it easy to set the variable on/off. @@ -186,8 +185,9 @@ static LIBYUV_BOOL TestEnv(const char*) { LIBYUV_API SAFEBUFFERS int InitCpuFlags(void) { + // TODO(fbarchard): swap kCpuInit logic so 0 means uninitialized. + int cpu_info = 0; #if !defined(__pnacl__) && !defined(__CLR_VER) && defined(CPU_X86) - uint32 cpu_info0[4] = { 0, 0, 0, 0 }; uint32 cpu_info1[4] = { 0, 0, 0, 0 }; uint32 cpu_info7[4] = { 0, 0, 0, 0 }; @@ -196,92 +196,102 @@ int InitCpuFlags(void) { if (cpu_info0[0] >= 7) { CpuId(7, 0, cpu_info7); } - cpu_info_ = ((cpu_info1[3] & 0x04000000) ? kCpuHasSSE2 : 0) | - ((cpu_info1[2] & 0x00000200) ? kCpuHasSSSE3 : 0) | - ((cpu_info1[2] & 0x00080000) ? kCpuHasSSE41 : 0) | - ((cpu_info1[2] & 0x00100000) ? kCpuHasSSE42 : 0) | - ((cpu_info7[1] & 0x00000200) ? kCpuHasERMS : 0) | - ((cpu_info1[2] & 0x00001000) ? kCpuHasFMA3 : 0) | - kCpuHasX86; + cpu_info = ((cpu_info1[3] & 0x04000000) ? kCpuHasSSE2 : 0) | + ((cpu_info1[2] & 0x00000200) ? kCpuHasSSSE3 : 0) | + ((cpu_info1[2] & 0x00080000) ? kCpuHasSSE41 : 0) | + ((cpu_info1[2] & 0x00100000) ? kCpuHasSSE42 : 0) | + ((cpu_info7[1] & 0x00000200) ? kCpuHasERMS : 0) | + ((cpu_info1[2] & 0x00001000) ? kCpuHasFMA3 : 0) | + kCpuHasX86; #ifdef HAS_XGETBV - if ((cpu_info1[2] & 0x18000000) == 0x18000000 && // AVX and OSSave - TestOsSaveYmm()) { // Saves YMM. - cpu_info_ |= ((cpu_info7[1] & 0x00000020) ? kCpuHasAVX2 : 0) | - kCpuHasAVX; + // AVX requires CPU has AVX, XSAVE and OSXSave for xgetbv + if (((cpu_info1[2] & 0x1c000000) == 0x1c000000) && // AVX and OSXSave + ((GetXCR0() & 6) == 6)) { // Test OS saves YMM registers + cpu_info |= ((cpu_info7[1] & 0x00000020) ? kCpuHasAVX2 : 0) | kCpuHasAVX; + + // Detect AVX512bw + if ((GetXCR0() & 0xe0) == 0xe0) { + cpu_info |= (cpu_info7[1] & 0x40000000) ? kCpuHasAVX3 : 0; + } } #endif + // Environment variable overrides for testing. if (TestEnv("LIBYUV_DISABLE_X86")) { - cpu_info_ &= ~kCpuHasX86; + cpu_info &= ~kCpuHasX86; } if (TestEnv("LIBYUV_DISABLE_SSE2")) { - cpu_info_ &= ~kCpuHasSSE2; + cpu_info &= ~kCpuHasSSE2; } if (TestEnv("LIBYUV_DISABLE_SSSE3")) { - cpu_info_ &= ~kCpuHasSSSE3; + cpu_info &= ~kCpuHasSSSE3; } if (TestEnv("LIBYUV_DISABLE_SSE41")) { - cpu_info_ &= ~kCpuHasSSE41; + cpu_info &= ~kCpuHasSSE41; } if (TestEnv("LIBYUV_DISABLE_SSE42")) { - cpu_info_ &= ~kCpuHasSSE42; + cpu_info &= ~kCpuHasSSE42; } if (TestEnv("LIBYUV_DISABLE_AVX")) { - cpu_info_ &= ~kCpuHasAVX; + cpu_info &= ~kCpuHasAVX; } if (TestEnv("LIBYUV_DISABLE_AVX2")) { - cpu_info_ &= ~kCpuHasAVX2; + cpu_info &= ~kCpuHasAVX2; } if (TestEnv("LIBYUV_DISABLE_ERMS")) { - cpu_info_ &= ~kCpuHasERMS; + cpu_info &= ~kCpuHasERMS; } if (TestEnv("LIBYUV_DISABLE_FMA3")) { - cpu_info_ &= ~kCpuHasFMA3; + cpu_info &= ~kCpuHasFMA3; + } + if (TestEnv("LIBYUV_DISABLE_AVX3")) { + cpu_info &= ~kCpuHasAVX3; } -#elif defined(__mips__) && defined(__linux__) - // Linux mips parse text file for dsp detect. - cpu_info_ = MipsCpuCaps("dsp"); // set kCpuHasMIPS_DSP. -#if defined(__mips_dspr2) - cpu_info_ |= kCpuHasMIPS_DSPR2; #endif - cpu_info_ |= kCpuHasMIPS; +#if defined(__mips__) && defined(__linux__) +#if defined(__mips_dspr2) + cpu_info |= kCpuHasMIPS_DSPR2; +#endif + cpu_info |= kCpuHasMIPS; if (getenv("LIBYUV_DISABLE_MIPS")) { - cpu_info_ &= ~kCpuHasMIPS; - } - if (getenv("LIBYUV_DISABLE_MIPS_DSP")) { - cpu_info_ &= ~kCpuHasMIPS_DSP; + cpu_info &= ~kCpuHasMIPS; } if (getenv("LIBYUV_DISABLE_MIPS_DSPR2")) { - cpu_info_ &= ~kCpuHasMIPS_DSPR2; + cpu_info &= ~kCpuHasMIPS_DSPR2; } -#elif defined(__arm__) || defined(__aarch64__) +#endif +#if defined(__arm__) || defined(__aarch64__) // gcc -mfpu=neon defines __ARM_NEON__ // __ARM_NEON__ generates code that requires Neon. NaCL also requires Neon. // For Linux, /proc/cpuinfo can be tested but without that assume Neon. #if defined(__ARM_NEON__) || defined(__native_client__) || !defined(__linux__) - cpu_info_ = kCpuHasNEON; + cpu_info = kCpuHasNEON; // For aarch64(arm64), /proc/cpuinfo's feature is not complete, e.g. no neon // flag in it. // So for aarch64, neon enabling is hard coded here. -#elif defined(__aarch64__) - cpu_info_ = kCpuHasNEON; +#endif +#if defined(__aarch64__) + cpu_info = kCpuHasNEON; #else // Linux arm parse text file for neon detect. - cpu_info_ = ArmCpuCaps("/proc/cpuinfo"); + cpu_info = ArmCpuCaps("/proc/cpuinfo"); #endif - cpu_info_ |= kCpuHasARM; + cpu_info |= kCpuHasARM; if (TestEnv("LIBYUV_DISABLE_NEON")) { - cpu_info_ &= ~kCpuHasNEON; + cpu_info &= ~kCpuHasNEON; } #endif // __arm__ if (TestEnv("LIBYUV_DISABLE_ASM")) { - cpu_info_ = 0; + cpu_info = 0; } - return cpu_info_; + cpu_info |= kCpuInitialized; + cpu_info_ = cpu_info; + return cpu_info; } +// Note that use of this function is not thread safe. LIBYUV_API void MaskCpuFlags(int enable_flags) { cpu_info_ = InitCpuFlags() & enable_flags; diff --git a/TMessagesProj/jni/libyuv/source/format_conversion.cc b/TMessagesProj/jni/libyuv/source/format_conversion.cc deleted file mode 100644 index 3c173715..00000000 --- a/TMessagesProj/jni/libyuv/source/format_conversion.cc +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright 2011 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "libyuv/format_conversion.h" - -#include "libyuv/basic_types.h" -#include "libyuv/cpu_id.h" -#include "libyuv/video_common.h" -#include "libyuv/row.h" - -#ifdef __cplusplus -namespace libyuv { -extern "C" { -#endif - -// generate a selector mask useful for pshufb -static uint32 GenerateSelector(int select0, int select1) { - return (uint32)(select0) | - (uint32)((select1 + 4) << 8) | - (uint32)((select0 + 8) << 16) | - (uint32)((select1 + 12) << 24); -} - -static int MakeSelectors(const int blue_index, - const int green_index, - const int red_index, - uint32 dst_fourcc_bayer, - uint32* index_map) { - // Now build a lookup table containing the indices for the four pixels in each - // 2x2 Bayer grid. - switch (dst_fourcc_bayer) { - case FOURCC_BGGR: - index_map[0] = GenerateSelector(blue_index, green_index); - index_map[1] = GenerateSelector(green_index, red_index); - break; - case FOURCC_GBRG: - index_map[0] = GenerateSelector(green_index, blue_index); - index_map[1] = GenerateSelector(red_index, green_index); - break; - case FOURCC_RGGB: - index_map[0] = GenerateSelector(red_index, green_index); - index_map[1] = GenerateSelector(green_index, blue_index); - break; - case FOURCC_GRBG: - index_map[0] = GenerateSelector(green_index, red_index); - index_map[1] = GenerateSelector(blue_index, green_index); - break; - default: - return -1; // Bad FourCC - } - return 0; -} - -// Converts 32 bit ARGB to Bayer RGB formats. -LIBYUV_API -int ARGBToBayer(const uint8* src_argb, int src_stride_argb, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height, - uint32 dst_fourcc_bayer) { - int y; - const int blue_index = 0; // Offsets for ARGB format - const int green_index = 1; - const int red_index = 2; - uint32 index_map[2]; - void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) = ARGBToBayerRow_C; - if (height < 0) { - height = -height; - src_argb = src_argb + (height - 1) * src_stride_argb; - src_stride_argb = -src_stride_argb; - } -#if defined(HAS_ARGBTOBAYERROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerRow_SSSE3; - } - } -#elif defined(HAS_ARGBTOBAYERROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - ARGBToBayerRow = ARGBToBayerRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerRow_NEON; - } - } -#endif - if (MakeSelectors(blue_index, green_index, red_index, - dst_fourcc_bayer, index_map)) { - return -1; // Bad FourCC - } - - for (y = 0; y < height; ++y) { - ARGBToBayerRow(src_argb, dst_bayer, index_map[y & 1], width); - src_argb += src_stride_argb; - dst_bayer += dst_stride_bayer; - } - return 0; -} - -#define AVG(a, b) (((a) + (b)) >> 1) - -static void BayerRowBG(const uint8* src_bayer0, int src_stride_bayer, - uint8* dst_argb, int pix) { - const uint8* src_bayer1 = src_bayer0 + src_stride_bayer; - uint8 g = src_bayer0[1]; - uint8 r = src_bayer1[1]; - int x; - for (x = 0; x < pix - 2; x += 2) { - dst_argb[0] = src_bayer0[0]; - dst_argb[1] = AVG(g, src_bayer0[1]); - dst_argb[2] = AVG(r, src_bayer1[1]); - dst_argb[3] = 255U; - dst_argb[4] = AVG(src_bayer0[0], src_bayer0[2]); - dst_argb[5] = src_bayer0[1]; - dst_argb[6] = src_bayer1[1]; - dst_argb[7] = 255U; - g = src_bayer0[1]; - r = src_bayer1[1]; - src_bayer0 += 2; - src_bayer1 += 2; - dst_argb += 8; - } - dst_argb[0] = src_bayer0[0]; - dst_argb[1] = AVG(g, src_bayer0[1]); - dst_argb[2] = AVG(r, src_bayer1[1]); - dst_argb[3] = 255U; - if (!(pix & 1)) { - dst_argb[4] = src_bayer0[0]; - dst_argb[5] = src_bayer0[1]; - dst_argb[6] = src_bayer1[1]; - dst_argb[7] = 255U; - } -} - -static void BayerRowRG(const uint8* src_bayer0, int src_stride_bayer, - uint8* dst_argb, int pix) { - const uint8* src_bayer1 = src_bayer0 + src_stride_bayer; - uint8 g = src_bayer0[1]; - uint8 b = src_bayer1[1]; - int x; - for (x = 0; x < pix - 2; x += 2) { - dst_argb[0] = AVG(b, src_bayer1[1]); - dst_argb[1] = AVG(g, src_bayer0[1]); - dst_argb[2] = src_bayer0[0]; - dst_argb[3] = 255U; - dst_argb[4] = src_bayer1[1]; - dst_argb[5] = src_bayer0[1]; - dst_argb[6] = AVG(src_bayer0[0], src_bayer0[2]); - dst_argb[7] = 255U; - g = src_bayer0[1]; - b = src_bayer1[1]; - src_bayer0 += 2; - src_bayer1 += 2; - dst_argb += 8; - } - dst_argb[0] = AVG(b, src_bayer1[1]); - dst_argb[1] = AVG(g, src_bayer0[1]); - dst_argb[2] = src_bayer0[0]; - dst_argb[3] = 255U; - if (!(pix & 1)) { - dst_argb[4] = src_bayer1[1]; - dst_argb[5] = src_bayer0[1]; - dst_argb[6] = src_bayer0[0]; - dst_argb[7] = 255U; - } -} - -static void BayerRowGB(const uint8* src_bayer0, int src_stride_bayer, - uint8* dst_argb, int pix) { - const uint8* src_bayer1 = src_bayer0 + src_stride_bayer; - uint8 b = src_bayer0[1]; - int x; - for (x = 0; x < pix - 2; x += 2) { - dst_argb[0] = AVG(b, src_bayer0[1]); - dst_argb[1] = src_bayer0[0]; - dst_argb[2] = src_bayer1[0]; - dst_argb[3] = 255U; - dst_argb[4] = src_bayer0[1]; - dst_argb[5] = AVG(src_bayer0[0], src_bayer0[2]); - dst_argb[6] = AVG(src_bayer1[0], src_bayer1[2]); - dst_argb[7] = 255U; - b = src_bayer0[1]; - src_bayer0 += 2; - src_bayer1 += 2; - dst_argb += 8; - } - dst_argb[0] = AVG(b, src_bayer0[1]); - dst_argb[1] = src_bayer0[0]; - dst_argb[2] = src_bayer1[0]; - dst_argb[3] = 255U; - if (!(pix & 1)) { - dst_argb[4] = src_bayer0[1]; - dst_argb[5] = src_bayer0[0]; - dst_argb[6] = src_bayer1[0]; - dst_argb[7] = 255U; - } -} - -static void BayerRowGR(const uint8* src_bayer0, int src_stride_bayer, - uint8* dst_argb, int pix) { - const uint8* src_bayer1 = src_bayer0 + src_stride_bayer; - uint8 r = src_bayer0[1]; - int x; - for (x = 0; x < pix - 2; x += 2) { - dst_argb[0] = src_bayer1[0]; - dst_argb[1] = src_bayer0[0]; - dst_argb[2] = AVG(r, src_bayer0[1]); - dst_argb[3] = 255U; - dst_argb[4] = AVG(src_bayer1[0], src_bayer1[2]); - dst_argb[5] = AVG(src_bayer0[0], src_bayer0[2]); - dst_argb[6] = src_bayer0[1]; - dst_argb[7] = 255U; - r = src_bayer0[1]; - src_bayer0 += 2; - src_bayer1 += 2; - dst_argb += 8; - } - dst_argb[0] = src_bayer1[0]; - dst_argb[1] = src_bayer0[0]; - dst_argb[2] = AVG(r, src_bayer0[1]); - dst_argb[3] = 255U; - if (!(pix & 1)) { - dst_argb[4] = src_bayer1[0]; - dst_argb[5] = src_bayer0[0]; - dst_argb[6] = src_bayer0[1]; - dst_argb[7] = 255U; - } -} - -// Converts any Bayer RGB format to ARGB. -LIBYUV_API -int BayerToARGB(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int dst_stride_argb, - int width, int height, - uint32 src_fourcc_bayer) { - int y; - void (*BayerRow0)(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int pix); - void (*BayerRow1)(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int pix); - if (height < 0) { - height = -height; - dst_argb = dst_argb + (height - 1) * dst_stride_argb; - dst_stride_argb = -dst_stride_argb; - } - switch (src_fourcc_bayer) { - case FOURCC_BGGR: - BayerRow0 = BayerRowBG; - BayerRow1 = BayerRowGR; - break; - case FOURCC_GBRG: - BayerRow0 = BayerRowGB; - BayerRow1 = BayerRowRG; - break; - case FOURCC_GRBG: - BayerRow0 = BayerRowGR; - BayerRow1 = BayerRowBG; - break; - case FOURCC_RGGB: - BayerRow0 = BayerRowRG; - BayerRow1 = BayerRowGB; - break; - default: - return -1; // Bad FourCC - } - - for (y = 0; y < height - 1; y += 2) { - BayerRow0(src_bayer, src_stride_bayer, dst_argb, width); - BayerRow1(src_bayer + src_stride_bayer, -src_stride_bayer, - dst_argb + dst_stride_argb, width); - src_bayer += src_stride_bayer * 2; - dst_argb += dst_stride_argb * 2; - } - if (height & 1) { - BayerRow0(src_bayer, src_stride_bayer, dst_argb, width); - } - return 0; -} - -// Converts any Bayer RGB format to ARGB. -LIBYUV_API -int BayerToI420(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_y, int dst_stride_y, - uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, - int width, int height, - uint32 src_fourcc_bayer) { - void (*BayerRow0)(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int pix); - void (*BayerRow1)(const uint8* src_bayer, int src_stride_bayer, - uint8* dst_argb, int pix); - - void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = - ARGBToYRow_C; - // Negative height means invert the image. - if (height < 0) { - int halfheight; - height = -height; - halfheight = (height + 1) >> 1; - dst_y = dst_y + (height - 1) * dst_stride_y; - dst_u = dst_u + (halfheight - 1) * dst_stride_u; - dst_v = dst_v + (halfheight - 1) * dst_stride_v; - dst_stride_y = -dst_stride_y; - dst_stride_u = -dst_stride_u; - dst_stride_v = -dst_stride_v; - } -#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; - ARGBToYRow = ARGBToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; - ARGBToUVRow = ARGBToUVRow_SSSE3; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } - } -#elif defined(HAS_ARGBTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - ARGBToYRow = ARGBToYRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - ARGBToYRow = ARGBToYRow_NEON; - } - } -#endif -#if defined(HAS_ARGBTOUVROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 16) { - ARGBToUVRow = ARGBToUVRow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_NEON; - } - } -#endif - - switch (src_fourcc_bayer) { - case FOURCC_BGGR: - BayerRow0 = BayerRowBG; - BayerRow1 = BayerRowGR; - break; - case FOURCC_GBRG: - BayerRow0 = BayerRowGB; - BayerRow1 = BayerRowRG; - break; - case FOURCC_GRBG: - BayerRow0 = BayerRowGR; - BayerRow1 = BayerRowBG; - break; - case FOURCC_RGGB: - BayerRow0 = BayerRowRG; - BayerRow1 = BayerRowGB; - break; - default: - return -1; // Bad FourCC - } - - { - // Allocate 2 rows of ARGB. - const int kRowSize = (width * 4 + 15) & ~15; - align_buffer_64(row, kRowSize * 2); - int y; - for (y = 0; y < height - 1; y += 2) { - BayerRow0(src_bayer, src_stride_bayer, row, width); - BayerRow1(src_bayer + src_stride_bayer, -src_stride_bayer, - row + kRowSize, width); - ARGBToUVRow(row, kRowSize, dst_u, dst_v, width); - ARGBToYRow(row, dst_y, width); - ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width); - src_bayer += src_stride_bayer * 2; - dst_y += dst_stride_y * 2; - dst_u += dst_stride_u; - dst_v += dst_stride_v; - } - if (height & 1) { - BayerRow0(src_bayer, src_stride_bayer, row, width); - ARGBToUVRow(row, 0, dst_u, dst_v, width); - ARGBToYRow(row, dst_y, width); - } - free_aligned_buffer_64(row); - } - return 0; -} - -// Convert I420 to Bayer. -LIBYUV_API -int I420ToBayer(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_bayer, int dst_stride_bayer, - int width, int height, - uint32 dst_fourcc_bayer) { - void (*I422ToARGBRow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToARGBRow_C; - void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) = ARGBToBayerRow_C; - const int blue_index = 0; // Offsets for ARGB format - const int green_index = 1; - const int red_index = 2; - uint32 index_map[2]; - // Negative height means invert the image. - if (height < 0) { - int halfheight; - height = -height; - halfheight = (height + 1) >> 1; - src_y = src_y + (height - 1) * src_stride_y; - src_u = src_u + (halfheight - 1) * src_stride_u; - src_v = src_v + (halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; - src_stride_u = -src_stride_u; - src_stride_v = -src_stride_v; - } -#if defined(HAS_I422TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToARGBRow = I422ToARGBRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToARGBRow = I422ToARGBRow_SSSE3; - } - } -#endif -#if defined(HAS_I422TOARGBROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { - I422ToARGBRow = I422ToARGBRow_Any_AVX2; - if (IS_ALIGNED(width, 16)) { - I422ToARGBRow = I422ToARGBRow_AVX2; - } - } -#endif -#if defined(HAS_I422TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - I422ToARGBRow = I422ToARGBRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - I422ToARGBRow = I422ToARGBRow_NEON; - } - } -#endif -#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && - IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && - IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && - IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2)) { - I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; - } -#endif - -#if defined(HAS_ARGBTOBAYERROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerRow_SSSE3; - } - } -#elif defined(HAS_ARGBTOBAYERROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - ARGBToBayerRow = ARGBToBayerRow_Any_NEON; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerRow_NEON; - } - } -#endif - - if (MakeSelectors(blue_index, green_index, red_index, - dst_fourcc_bayer, index_map)) { - return -1; // Bad FourCC - } - { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - int y; - for (y = 0; y < height; ++y) { - I422ToARGBRow(src_y, src_u, src_v, row, width); - ARGBToBayerRow(row, dst_bayer, index_map[y & 1], width); - dst_bayer += dst_stride_bayer; - src_y += src_stride_y; - if (y & 1) { - src_u += src_stride_u; - src_v += src_stride_v; - } - } - free_aligned_buffer_64(row); - } - return 0; -} - -#define MAKEBAYERFOURCC(BAYER) \ -LIBYUV_API \ -int Bayer##BAYER##ToI420(const uint8* src_bayer, int src_stride_bayer, \ - uint8* dst_y, int dst_stride_y, \ - uint8* dst_u, int dst_stride_u, \ - uint8* dst_v, int dst_stride_v, \ - int width, int height) { \ - return BayerToI420(src_bayer, src_stride_bayer, \ - dst_y, dst_stride_y, \ - dst_u, dst_stride_u, \ - dst_v, dst_stride_v, \ - width, height, \ - FOURCC_##BAYER); \ -} \ - \ -LIBYUV_API \ -int I420ToBayer##BAYER(const uint8* src_y, int src_stride_y, \ - const uint8* src_u, int src_stride_u, \ - const uint8* src_v, int src_stride_v, \ - uint8* dst_bayer, int dst_stride_bayer, \ - int width, int height) { \ - return I420ToBayer(src_y, src_stride_y, \ - src_u, src_stride_u, \ - src_v, src_stride_v, \ - dst_bayer, dst_stride_bayer, \ - width, height, \ - FOURCC_##BAYER); \ -} \ - \ -LIBYUV_API \ -int ARGBToBayer##BAYER(const uint8* src_argb, int src_stride_argb, \ - uint8* dst_bayer, int dst_stride_bayer, \ - int width, int height) { \ - return ARGBToBayer(src_argb, src_stride_argb, \ - dst_bayer, dst_stride_bayer, \ - width, height, \ - FOURCC_##BAYER); \ -} \ - \ -LIBYUV_API \ -int Bayer##BAYER##ToARGB(const uint8* src_bayer, int src_stride_bayer, \ - uint8* dst_argb, int dst_stride_argb, \ - int width, int height) { \ - return BayerToARGB(src_bayer, src_stride_bayer, \ - dst_argb, dst_stride_argb, \ - width, height, \ - FOURCC_##BAYER); \ -} - -MAKEBAYERFOURCC(BGGR) -MAKEBAYERFOURCC(GBRG) -MAKEBAYERFOURCC(GRBG) -MAKEBAYERFOURCC(RGGB) - -#ifdef __cplusplus -} // extern "C" -} // namespace libyuv -#endif diff --git a/TMessagesProj/jni/libyuv/source/mjpeg_decoder.cc b/TMessagesProj/jni/libyuv/source/mjpeg_decoder.cc index 36028c3c..50818418 100644 --- a/TMessagesProj/jni/libyuv/source/mjpeg_decoder.cc +++ b/TMessagesProj/jni/libyuv/source/mjpeg_decoder.cc @@ -18,6 +18,12 @@ // Must be included before jpeglib. #include #define HAVE_SETJMP + +#if defined(_MSC_VER) +// disable warning 4324: structure was padded due to __declspec(align()) +#pragma warning(disable:4324) +#endif + #endif struct FILE; // For jpeglib.h. @@ -53,8 +59,7 @@ const int MJpegDecoder::kColorSpaceYCCK = JCS_YCCK; // Methods that are passed to jpeglib. boolean fill_input_buffer(jpeg_decompress_struct* cinfo); void init_source(jpeg_decompress_struct* cinfo); -void skip_input_data(jpeg_decompress_struct* cinfo, - long num_bytes); // NOLINT +void skip_input_data(jpeg_decompress_struct* cinfo, long num_bytes); // NOLINT void term_source(jpeg_decompress_struct* cinfo); void ErrorHandler(jpeg_common_struct* cinfo); @@ -423,8 +428,7 @@ boolean fill_input_buffer(j_decompress_ptr cinfo) { return TRUE; } -void skip_input_data(j_decompress_ptr cinfo, - long num_bytes) { // NOLINT +void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { // NOLINT cinfo->src->next_input_byte += num_bytes; } diff --git a/TMessagesProj/jni/libyuv/source/mjpeg_validate.cc b/TMessagesProj/jni/libyuv/source/mjpeg_validate.cc index 23d22d09..9c488320 100644 --- a/TMessagesProj/jni/libyuv/source/mjpeg_validate.cc +++ b/TMessagesProj/jni/libyuv/source/mjpeg_validate.cc @@ -10,36 +10,60 @@ #include "libyuv/mjpeg_decoder.h" +#include // For memchr. + #ifdef __cplusplus namespace libyuv { extern "C" { #endif -// Helper function to validate the jpeg appears intact. -// TODO(fbarchard): Optimize case where SOI is found but EOI is not. -LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size) { - size_t i; - if (sample_size < 64) { - // ERROR: Invalid jpeg size: sample_size - return LIBYUV_FALSE; - } - if (sample[0] != 0xff || sample[1] != 0xd8) { // Start Of Image - // ERROR: Invalid jpeg initial start code - return LIBYUV_FALSE; - } - for (i = sample_size - 2; i > 1;) { - if (sample[i] != 0xd9) { - if (sample[i] == 0xff && sample[i + 1] == 0xd9) { // End Of Image +// Helper function to scan for EOI marker (0xff 0xd9). +static LIBYUV_BOOL ScanEOI(const uint8* sample, size_t sample_size) { + if (sample_size >= 2) { + const uint8* end = sample + sample_size - 1; + const uint8* it = sample; + while (it < end) { + // TODO(fbarchard): scan for 0xd9 instead. + it = static_cast(memchr(it, 0xff, end - it)); + if (it == NULL) { + break; + } + if (it[1] == 0xd9) { return LIBYUV_TRUE; // Success: Valid jpeg. } - --i; + ++it; // Skip over current 0xff. } - --i; } // ERROR: Invalid jpeg end code not found. Size sample_size return LIBYUV_FALSE; } +// Helper function to validate the jpeg appears intact. +LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size) { + // Maximum size that ValidateJpeg will consider valid. + const size_t kMaxJpegSize = 0x7fffffffull; + const size_t kBackSearchSize = 1024; + if (sample_size < 64 || sample_size > kMaxJpegSize || !sample) { + // ERROR: Invalid jpeg size: sample_size + return LIBYUV_FALSE; + } + if (sample[0] != 0xff || sample[1] != 0xd8) { // SOI marker + // ERROR: Invalid jpeg initial start code + return LIBYUV_FALSE; + } + + // Look for the End Of Image (EOI) marker near the end of the buffer. + if (sample_size > kBackSearchSize) { + if (ScanEOI(sample + sample_size - kBackSearchSize, kBackSearchSize)) { + return LIBYUV_TRUE; // Success: Valid jpeg. + } + // Reduce search size for forward search. + sample_size = sample_size - kBackSearchSize + 1; + } + // Step over SOI marker and scan for EOI. + return ScanEOI(sample + 2, sample_size - 2); +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/TMessagesProj/jni/libyuv/source/planar_functions.cc b/TMessagesProj/jni/libyuv/source/planar_functions.cc index 3857008c..536e1d52 100644 --- a/TMessagesProj/jni/libyuv/source/planar_functions.cc +++ b/TMessagesProj/jni/libyuv/source/planar_functions.cc @@ -17,6 +17,7 @@ #include "libyuv/mjpeg_decoder.h" #endif #include "libyuv/row.h" +#include "libyuv/scale_row.h" // for ScaleRowDown2 #ifdef __cplusplus namespace libyuv { @@ -41,16 +42,14 @@ void CopyPlane(const uint8* src_y, int src_stride_y, if (src_y == dst_y && src_stride_y == dst_stride_y) { return; } -#if defined(HAS_COPYROW_X86) - if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { - CopyRow = CopyRow_X86; +#if defined(HAS_COPYROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; } #endif -#if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && - IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - CopyRow = CopyRow_SSE2; +#if defined(HAS_COPYROW_AVX) + if (TestCpuFlag(kCpuHasAVX)) { + CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX; } #endif #if defined(HAS_COPYROW_ERMS) @@ -59,8 +58,8 @@ void CopyPlane(const uint8* src_y, int src_stride_y, } #endif #if defined(HAS_COPYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { - CopyRow = CopyRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON; } #endif #if defined(HAS_COPYROW_MIPS) @@ -90,15 +89,8 @@ void CopyPlane_16(const uint16* src_y, int src_stride_y, height = 1; src_stride_y = dst_stride_y = 0; } -#if defined(HAS_COPYROW_16_X86) - if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { - CopyRow = CopyRow_16_X86; - } -#endif #if defined(HAS_COPYROW_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && - IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32)) { CopyRow = CopyRow_16_SSE2; } #endif @@ -239,25 +231,35 @@ void MirrorPlane(const uint8* src_y, int src_stride_y, src_stride_y = -src_stride_y; } #if defined(HAS_MIRRORROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { - MirrorRow = MirrorRow_NEON; - } -#endif -#if defined(HAS_MIRRORROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { - MirrorRow = MirrorRow_SSE2; + if (TestCpuFlag(kCpuHasNEON)) { + MirrorRow = MirrorRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + MirrorRow = MirrorRow_NEON; + } } #endif #if defined(HAS_MIRRORROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) && - IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - MirrorRow = MirrorRow_SSSE3; + if (TestCpuFlag(kCpuHasSSSE3)) { + MirrorRow = MirrorRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + MirrorRow = MirrorRow_SSSE3; + } } #endif #if defined(HAS_MIRRORROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 32)) { - MirrorRow = MirrorRow_AVX2; + if (TestCpuFlag(kCpuHasAVX2)) { + MirrorRow = MirrorRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + MirrorRow = MirrorRow_AVX2; + } + } +#endif +// TODO(fbarchard): Mirror on mips handle unaligned memory. +#if defined(HAS_MIRRORROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && + IS_ALIGNED(dst_y, 4) && IS_ALIGNED(dst_stride_y, 4)) { + MirrorRow = MirrorRow_MIPS_DSPR2; } #endif @@ -278,9 +280,9 @@ int YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2, int width, int height) { int y; void (*YUY2ToUV422Row)(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) = + uint8* dst_u, uint8* dst_v, int width) = YUY2ToUV422Row_C; - void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) = + void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int width) = YUY2ToYRow_C; // Negative height means invert the image. if (height < 0) { @@ -298,23 +300,17 @@ int YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2, src_stride_yuy2 = dst_stride_y = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_YUY2TOYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2; YUY2ToYRow = YUY2ToYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { - YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2; - YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2; - if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) { - YUY2ToUV422Row = YUY2ToUV422Row_SSE2; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - YUY2ToYRow = YUY2ToYRow_SSE2; - } - } + YUY2ToUV422Row = YUY2ToUV422Row_SSE2; + YUY2ToYRow = YUY2ToYRow_SSE2; } } #endif #if defined(HAS_YUY2TOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2; YUY2ToYRow = YUY2ToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { @@ -324,7 +320,7 @@ int YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2, } #endif #if defined(HAS_YUY2TOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { YUY2ToYRow = YUY2ToYRow_Any_NEON; if (width >= 16) { YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON; @@ -356,10 +352,10 @@ int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, int width, int height) { int y; void (*UYVYToUV422Row)(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) = + uint8* dst_u, uint8* dst_v, int width) = UYVYToUV422Row_C; void (*UYVYToYRow)(const uint8* src_uyvy, - uint8* dst_y, int pix) = UYVYToYRow_C; + uint8* dst_y, int width) = UYVYToYRow_C; // Negative height means invert the image. if (height < 0) { height = -height; @@ -376,23 +372,17 @@ int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, src_stride_uyvy = dst_stride_y = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_UYVYTOYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { UYVYToUV422Row = UYVYToUV422Row_Any_SSE2; UYVYToYRow = UYVYToYRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { - UYVYToUV422Row = UYVYToUV422Row_Unaligned_SSE2; - UYVYToYRow = UYVYToYRow_Unaligned_SSE2; - if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) { - UYVYToUV422Row = UYVYToUV422Row_SSE2; - if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - UYVYToYRow = UYVYToYRow_SSE2; - } - } + UYVYToUV422Row = UYVYToUV422Row_SSE2; + UYVYToYRow = UYVYToYRow_SSE2; } } #endif #if defined(HAS_UYVYTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { UYVYToUV422Row = UYVYToUV422Row_Any_AVX2; UYVYToYRow = UYVYToYRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { @@ -402,7 +392,7 @@ int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, } #endif #if defined(HAS_UYVYTOYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { UYVYToYRow = UYVYToYRow_Any_NEON; if (width >= 16) { UYVYToUV422Row = UYVYToUV422Row_Any_NEON; @@ -497,22 +487,28 @@ int ARGBMirror(const uint8* src_argb, int src_stride_argb, src_argb = src_argb + (height - 1) * src_stride_argb; src_stride_argb = -src_stride_argb; } - -#if defined(HAS_ARGBMIRRORROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - ARGBMirrorRow = ARGBMirrorRow_SSSE3; +#if defined(HAS_ARGBMIRRORROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBMirrorRow = ARGBMirrorRow_Any_NEON; + if (IS_ALIGNED(width, 4)) { + ARGBMirrorRow = ARGBMirrorRow_NEON; + } + } +#endif +#if defined(HAS_ARGBMIRRORROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBMirrorRow = ARGBMirrorRow_Any_SSE2; + if (IS_ALIGNED(width, 4)) { + ARGBMirrorRow = ARGBMirrorRow_SSE2; + } } #endif #if defined(HAS_ARGBMIRRORROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 8)) { - ARGBMirrorRow = ARGBMirrorRow_AVX2; - } -#endif -#if defined(HAS_ARGBMIRRORROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) { - ARGBMirrorRow = ARGBMirrorRow_NEON; + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBMirrorRow = ARGBMirrorRow_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBMirrorRow = ARGBMirrorRow_AVX2; + } } #endif @@ -525,7 +521,7 @@ int ARGBMirror(const uint8* src_argb, int src_stride_argb, return 0; } -// Get a blender that optimized for the CPU, alignment and pixel count. +// Get a blender that optimized for the CPU and pixel count. // As there are 6 blenders to choose from, the caller should try to use // the same blend function for all pixels if possible. LIBYUV_API @@ -538,11 +534,6 @@ ARGBBlendRow GetARGBBlend() { return ARGBBlendRow; } #endif -#if defined(HAS_ARGBBLENDROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2)) { - ARGBBlendRow = ARGBBlendRow_SSE2; - } -#endif #if defined(HAS_ARGBBLENDROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { ARGBBlendRow = ARGBBlendRow_NEON; @@ -587,6 +578,167 @@ int ARGBBlend(const uint8* src_argb0, int src_stride_argb0, return 0; } +// Alpha Blend plane and store to destination. +LIBYUV_API +int BlendPlane(const uint8* src_y0, int src_stride_y0, + const uint8* src_y1, int src_stride_y1, + const uint8* alpha, int alpha_stride, + uint8* dst_y, int dst_stride_y, + int width, int height) { + int y; + void (*BlendPlaneRow)(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width) = BlendPlaneRow_C; + if (!src_y0 || !src_y1 || !alpha || !dst_y || width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_y = dst_y + (height - 1) * dst_stride_y; + dst_stride_y = -dst_stride_y; + } + + // Coalesce rows for Y plane. + if (src_stride_y0 == width && + src_stride_y1 == width && + alpha_stride == width && + dst_stride_y == width) { + width *= height; + height = 1; + src_stride_y0 = src_stride_y1 = alpha_stride = dst_stride_y = 0; + } + +#if defined(HAS_BLENDPLANEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + BlendPlaneRow = BlendPlaneRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + BlendPlaneRow = BlendPlaneRow_SSSE3; + } + } +#endif +#if defined(HAS_BLENDPLANEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + BlendPlaneRow = BlendPlaneRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + BlendPlaneRow = BlendPlaneRow_AVX2; + } + } +#endif + + for (y = 0; y < height; ++y) { + BlendPlaneRow(src_y0, src_y1, alpha, dst_y, width); + src_y0 += src_stride_y0; + src_y1 += src_stride_y1; + alpha += alpha_stride; + dst_y += dst_stride_y; + } + return 0; +} + +#define MAXTWIDTH 2048 +// Alpha Blend YUV images and store to destination. +LIBYUV_API +int I420Blend(const uint8* src_y0, int src_stride_y0, + const uint8* src_u0, int src_stride_u0, + const uint8* src_v0, int src_stride_v0, + const uint8* src_y1, int src_stride_y1, + const uint8* src_u1, int src_stride_u1, + const uint8* src_v1, int src_stride_v1, + const uint8* alpha, int alpha_stride, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height) { + int y; + // Half width/height for UV. + int halfwidth = (width + 1) >> 1; + void (*BlendPlaneRow)(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width) = BlendPlaneRow_C; + void (*ScaleRowDown2)(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) = ScaleRowDown2Box_C; + if (!src_y0 || !src_u0 || !src_v0 || !src_y1 || !src_u1 || !src_v1 || + !alpha || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { + return -1; + } + + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_y = dst_y + (height - 1) * dst_stride_y; + dst_stride_y = -dst_stride_y; + } + + // Blend Y plane. + BlendPlane(src_y0, src_stride_y0, + src_y1, src_stride_y1, + alpha, alpha_stride, + dst_y, dst_stride_y, + width, height); + +#if defined(HAS_BLENDPLANEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + BlendPlaneRow = BlendPlaneRow_Any_SSSE3; + if (IS_ALIGNED(halfwidth, 8)) { + BlendPlaneRow = BlendPlaneRow_SSSE3; + } + } +#endif +#if defined(HAS_BLENDPLANEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + BlendPlaneRow = BlendPlaneRow_Any_AVX2; + if (IS_ALIGNED(halfwidth, 32)) { + BlendPlaneRow = BlendPlaneRow_AVX2; + } + } +#endif +#if defined(HAS_SCALEROWDOWN2_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleRowDown2 = ScaleRowDown2Box_Any_NEON; + if (IS_ALIGNED(halfwidth, 16)) { + ScaleRowDown2 = ScaleRowDown2Box_NEON; + } + } +#endif +#if defined(HAS_SCALEROWDOWN2_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ScaleRowDown2 = ScaleRowDown2Box_Any_SSSE3; + if (IS_ALIGNED(halfwidth, 16)) { + ScaleRowDown2 = ScaleRowDown2Box_SSSE3; + } + } +#endif +#if defined(HAS_SCALEROWDOWN2_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ScaleRowDown2 = ScaleRowDown2Box_Any_AVX2; + if (IS_ALIGNED(halfwidth, 32)) { + ScaleRowDown2 = ScaleRowDown2Box_AVX2; + } + } +#endif + + // Row buffer for intermediate alpha pixels. + align_buffer_64(halfalpha, halfwidth); + for (y = 0; y < height; y += 2) { + // last row of odd height image use 1 row of alpha instead of 2. + if (y == (height - 1)) { + alpha_stride = 0; + } + // Subsample 2 rows of UV to half width and half height. + ScaleRowDown2(alpha, alpha_stride, halfalpha, halfwidth); + alpha += alpha_stride * 2; + BlendPlaneRow(src_u0, src_u1, halfalpha, dst_u, halfwidth); + BlendPlaneRow(src_v0, src_v1, halfalpha, dst_v, halfwidth); + src_u0 += src_stride_u0; + src_u1 += src_stride_u1; + dst_u += dst_stride_u; + src_v0 += src_stride_v0; + src_v1 += src_stride_v1; + dst_v += dst_stride_v; + } + free_aligned_buffer_64(halfalpha); + return 0; +} + // Multiply 2 ARGB images and store to destination. LIBYUV_API int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, @@ -614,7 +766,7 @@ int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; } #if defined(HAS_ARGBMULTIPLYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBMultiplyRow = ARGBMultiplyRow_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBMultiplyRow = ARGBMultiplyRow_SSE2; @@ -622,7 +774,7 @@ int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBMULTIPLYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBMultiplyRow = ARGBMultiplyRow_Any_AVX2; if (IS_ALIGNED(width, 8)) { ARGBMultiplyRow = ARGBMultiplyRow_AVX2; @@ -630,7 +782,7 @@ int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBMULTIPLYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBMultiplyRow = ARGBMultiplyRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBMultiplyRow = ARGBMultiplyRow_NEON; @@ -674,13 +826,13 @@ int ARGBAdd(const uint8* src_argb0, int src_stride_argb0, height = 1; src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; } -#if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER) +#if defined(HAS_ARGBADDROW_SSE2) && (defined(_MSC_VER) && !defined(__clang__)) if (TestCpuFlag(kCpuHasSSE2)) { ARGBAddRow = ARGBAddRow_SSE2; } #endif -#if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { +#if defined(HAS_ARGBADDROW_SSE2) && !(defined(_MSC_VER) && !defined(__clang__)) + if (TestCpuFlag(kCpuHasSSE2)) { ARGBAddRow = ARGBAddRow_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBAddRow = ARGBAddRow_SSE2; @@ -688,7 +840,7 @@ int ARGBAdd(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBADDROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBAddRow = ARGBAddRow_Any_AVX2; if (IS_ALIGNED(width, 8)) { ARGBAddRow = ARGBAddRow_AVX2; @@ -696,7 +848,7 @@ int ARGBAdd(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBADDROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBAddRow = ARGBAddRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBAddRow = ARGBAddRow_NEON; @@ -741,7 +893,7 @@ int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; } #if defined(HAS_ARGBSUBTRACTROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBSubtractRow = ARGBSubtractRow_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBSubtractRow = ARGBSubtractRow_SSE2; @@ -749,7 +901,7 @@ int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBSUBTRACTROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBSubtractRow = ARGBSubtractRow_Any_AVX2; if (IS_ALIGNED(width, 8)) { ARGBSubtractRow = ARGBSubtractRow_AVX2; @@ -757,7 +909,7 @@ int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, } #endif #if defined(HAS_ARGBSUBTRACTROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBSubtractRow = ARGBSubtractRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBSubtractRow = ARGBSubtractRow_NEON; @@ -774,132 +926,67 @@ int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, } return 0; } - -// Convert I422 to BGRA. -LIBYUV_API -int I422ToBGRA(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_bgra, int dst_stride_bgra, - int width, int height) { +// Convert I422 to RGBA with matrix +static int I422ToRGBAMatrix(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_rgba, int dst_stride_rgba, + const struct YuvConstants* yuvconstants, + int width, int height) { int y; - void (*I422ToBGRARow)(const uint8* y_buf, + void (*I422ToRGBARow)(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, - int width) = I422ToBGRARow_C; - if (!src_y || !src_u || !src_v || - !dst_bgra || + const struct YuvConstants* yuvconstants, + int width) = I422ToRGBARow_C; + if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; - dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra; - dst_stride_bgra = -dst_stride_bgra; + dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; + dst_stride_rgba = -dst_stride_rgba; } - // Coalesce rows. - if (src_stride_y == width && - src_stride_u * 2 == width && - src_stride_v * 2 == width && - dst_stride_bgra == width * 4) { - width *= height; - height = 1; - src_stride_y = src_stride_u = src_stride_v = dst_stride_bgra = 0; - } -#if defined(HAS_I422TOBGRAROW_NEON) - if (TestCpuFlag(kCpuHasNEON)) { - I422ToBGRARow = I422ToBGRARow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - I422ToBGRARow = I422ToBGRARow_NEON; - } - } -#elif defined(HAS_I422TOBGRAROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToBGRARow = I422ToBGRARow_Any_SSSE3; +#if defined(HAS_I422TORGBAROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + I422ToRGBARow = I422ToRGBARow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) { - I422ToBGRARow = I422ToBGRARow_SSSE3; - } + I422ToRGBARow = I422ToRGBARow_SSSE3; } } -#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2) +#endif +#if defined(HAS_I422TORGBAROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + I422ToRGBARow = I422ToRGBARow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToRGBARow = I422ToRGBARow_AVX2; + } + } +#endif +#if defined(HAS_I422TORGBAROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + I422ToRGBARow = I422ToRGBARow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422ToRGBARow = I422ToRGBARow_NEON; + } + } +#endif +#if defined(HAS_I422TORGBAROW_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && - IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) { - I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2; + IS_ALIGNED(dst_rgba, 4) && IS_ALIGNED(dst_stride_rgba, 4)) { + I422ToRGBARow = I422ToRGBARow_MIPS_DSPR2; } #endif for (y = 0; y < height; ++y) { - I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width); - dst_bgra += dst_stride_bgra; - src_y += src_stride_y; - src_u += src_stride_u; - src_v += src_stride_v; - } - return 0; -} - -// Convert I422 to ABGR. -LIBYUV_API -int I422ToABGR(const uint8* src_y, int src_stride_y, - const uint8* src_u, int src_stride_u, - const uint8* src_v, int src_stride_v, - uint8* dst_abgr, int dst_stride_abgr, - int width, int height) { - int y; - void (*I422ToABGRRow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToABGRRow_C; - if (!src_y || !src_u || !src_v || - !dst_abgr || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr; - dst_stride_abgr = -dst_stride_abgr; - } - // Coalesce rows. - if (src_stride_y == width && - src_stride_u * 2 == width && - src_stride_v * 2 == width && - dst_stride_abgr == width * 4) { - width *= height; - height = 1; - src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0; - } -#if defined(HAS_I422TOABGRROW_NEON) - if (TestCpuFlag(kCpuHasNEON)) { - I422ToABGRRow = I422ToABGRRow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - I422ToABGRRow = I422ToABGRRow_NEON; - } - } -#elif defined(HAS_I422TOABGRROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToABGRRow = I422ToABGRRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) { - I422ToABGRRow = I422ToABGRRow_SSSE3; - } - } - } -#endif - - for (y = 0; y < height; ++y) { - I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width); - dst_abgr += dst_stride_abgr; + I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width); + dst_rgba += dst_stride_rgba; src_y += src_stride_y; src_u += src_stride_u; src_v += src_stride_v; @@ -914,59 +1001,27 @@ int I422ToRGBA(const uint8* src_y, int src_stride_y, const uint8* src_v, int src_stride_v, uint8* dst_rgba, int dst_stride_rgba, int width, int height) { - int y; - void (*I422ToRGBARow)(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) = I422ToRGBARow_C; - if (!src_y || !src_u || !src_v || - !dst_rgba || - width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; - dst_stride_rgba = -dst_stride_rgba; - } - // Coalesce rows. - if (src_stride_y == width && - src_stride_u * 2 == width && - src_stride_v * 2 == width && - dst_stride_rgba == width * 4) { - width *= height; - height = 1; - src_stride_y = src_stride_u = src_stride_v = dst_stride_rgba = 0; - } -#if defined(HAS_I422TORGBAROW_NEON) - if (TestCpuFlag(kCpuHasNEON)) { - I422ToRGBARow = I422ToRGBARow_Any_NEON; - if (IS_ALIGNED(width, 16)) { - I422ToRGBARow = I422ToRGBARow_NEON; - } - } -#elif defined(HAS_I422TORGBAROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - I422ToRGBARow = I422ToRGBARow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { - I422ToRGBARow = I422ToRGBARow_SSSE3; - } - } - } -#endif + return I422ToRGBAMatrix(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + dst_rgba, dst_stride_rgba, + &kYuvI601Constants, + width, height); +} - for (y = 0; y < height; ++y) { - I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width); - dst_rgba += dst_stride_rgba; - src_y += src_stride_y; - src_u += src_stride_u; - src_v += src_stride_v; - } - return 0; +// Convert I422 to BGRA. +LIBYUV_API +int I422ToBGRA(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_bgra, int dst_stride_bgra, + int width, int height) { + return I422ToRGBAMatrix(src_y, src_stride_y, + src_v, src_stride_v, // Swap U and V + src_u, src_stride_u, + dst_bgra, dst_stride_bgra, + &kYvuI601Constants, // Use Yvu matrix + width, height); } // Convert NV12 to RGB565. @@ -979,6 +1034,7 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y, void (*NV12ToRGB565Row)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C; if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) { @@ -991,14 +1047,23 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y, dst_stride_rgb565 = -dst_stride_rgb565; } #if defined(HAS_NV12TORGB565ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { NV12ToRGB565Row = NV12ToRGB565Row_SSSE3; } } -#elif defined(HAS_NV12TORGB565ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { +#endif +#if defined(HAS_NV12TORGB565ROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + NV12ToRGB565Row = NV12ToRGB565Row_AVX2; + } + } +#endif +#if defined(HAS_NV12TORGB565ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON; if (IS_ALIGNED(width, 8)) { NV12ToRGB565Row = NV12ToRGB565Row_NEON; @@ -1007,7 +1072,7 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y, #endif for (y = 0; y < height; ++y) { - NV12ToRGB565Row(src_y, src_uv, dst_rgb565, width); + NV12ToRGB565Row(src_y, src_uv, dst_rgb565, &kYuvI601Constants, width); dst_rgb565 += dst_stride_rgb565; src_y += src_stride_y; if (y & 1) { @@ -1017,50 +1082,52 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y, return 0; } -// Convert NV21 to RGB565. +// Convert RAW to RGB24. LIBYUV_API -int NV21ToRGB565(const uint8* src_y, int src_stride_y, - const uint8* src_vu, int src_stride_vu, - uint8* dst_rgb565, int dst_stride_rgb565, - int width, int height) { +int RAWToRGB24(const uint8* src_raw, int src_stride_raw, + uint8* dst_rgb24, int dst_stride_rgb24, + int width, int height) { int y; - void (*NV21ToRGB565Row)(const uint8* y_buf, - const uint8* src_vu, - uint8* rgb_buf, - int width) = NV21ToRGB565Row_C; - if (!src_y || !src_vu || !dst_rgb565 || + void (*RAWToRGB24Row)(const uint8* src_rgb, uint8* dst_rgb24, int width) = + RAWToRGB24Row_C; + if (!src_raw || !dst_rgb24 || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; - dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; - dst_stride_rgb565 = -dst_stride_rgb565; + src_raw = src_raw + (height - 1) * src_stride_raw; + src_stride_raw = -src_stride_raw; } -#if defined(HAS_NV21TORGB565ROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { - NV21ToRGB565Row = NV21ToRGB565Row_Any_SSSE3; + // Coalesce rows. + if (src_stride_raw == width * 3 && + dst_stride_rgb24 == width * 3) { + width *= height; + height = 1; + src_stride_raw = dst_stride_rgb24 = 0; + } +#if defined(HAS_RAWTORGB24ROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + RAWToRGB24Row = RAWToRGB24Row_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - NV21ToRGB565Row = NV21ToRGB565Row_SSSE3; + RAWToRGB24Row = RAWToRGB24Row_SSSE3; } } -#elif defined(HAS_NV21TORGB565ROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - NV21ToRGB565Row = NV21ToRGB565Row_Any_NEON; +#endif +#if defined(HAS_RAWTORGB24ROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + RAWToRGB24Row = RAWToRGB24Row_Any_NEON; if (IS_ALIGNED(width, 8)) { - NV21ToRGB565Row = NV21ToRGB565Row_NEON; + RAWToRGB24Row = RAWToRGB24Row_NEON; } } #endif for (y = 0; y < height; ++y) { - NV21ToRGB565Row(src_y, src_vu, dst_rgb565, width); - dst_rgb565 += dst_stride_rgb565; - src_y += src_stride_y; - if (y & 1) { - src_vu += src_stride_vu; - } + RAWToRGB24Row(src_raw, dst_rgb24, width); + src_raw += src_stride_raw; + dst_rgb24 += dst_stride_rgb24; } return 0; } @@ -1070,8 +1137,12 @@ void SetPlane(uint8* dst_y, int dst_stride_y, int width, int height, uint32 value) { int y; - uint32 v32 = value | (value << 8) | (value << 16) | (value << 24); - void (*SetRow)(uint8* dst, uint32 value, int pix) = SetRow_C; + void (*SetRow)(uint8* dst, uint8 value, int width) = SetRow_C; + if (height < 0) { + height = -height; + dst_y = dst_y + (height - 1) * dst_stride_y; + dst_stride_y = -dst_stride_y; + } // Coalesce rows. if (dst_stride_y == width) { width *= height; @@ -1079,21 +1150,30 @@ void SetPlane(uint8* dst_y, int dst_stride_y, dst_stride_y = 0; } #if defined(HAS_SETROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && - IS_ALIGNED(width, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - SetRow = SetRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + SetRow = SetRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + SetRow = SetRow_NEON; + } } #endif #if defined(HAS_SETROW_X86) - if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { - SetRow = SetRow_X86; + if (TestCpuFlag(kCpuHasX86)) { + SetRow = SetRow_Any_X86; + if (IS_ALIGNED(width, 4)) { + SetRow = SetRow_X86; + } + } +#endif +#if defined(HAS_SETROW_ERMS) + if (TestCpuFlag(kCpuHasERMS)) { + SetRow = SetRow_ERMS; } #endif // Set plane for (y = 0; y < height; ++y) { - SetRow(dst_y, v32, width); + SetRow(dst_y, value, width); dst_y += dst_stride_y; } } @@ -1112,7 +1192,7 @@ int I420Rect(uint8* dst_y, int dst_stride_y, uint8* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2); uint8* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2); if (!dst_y || !dst_u || !dst_v || - width <= 0 || height <= 0 || + width <= 0 || height == 0 || x < 0 || y < 0 || value_y < 0 || value_y > 255 || value_u < 0 || value_u > 255 || @@ -1132,11 +1212,18 @@ int ARGBRect(uint8* dst_argb, int dst_stride_argb, int dst_x, int dst_y, int width, int height, uint32 value) { + int y; + void (*ARGBSetRow)(uint8* dst_argb, uint32 value, int width) = ARGBSetRow_C; if (!dst_argb || - width <= 0 || height <= 0 || + width <= 0 || height == 0 || dst_x < 0 || dst_y < 0) { return -1; } + if (height < 0) { + height = -height; + dst_argb = dst_argb + (height - 1) * dst_stride_argb; + dst_stride_argb = -dst_stride_argb; + } dst_argb += dst_y * dst_stride_argb + dst_x * 4; // Coalesce rows. if (dst_stride_argb == width * 4) { @@ -1144,20 +1231,26 @@ int ARGBRect(uint8* dst_argb, int dst_stride_argb, height = 1; dst_stride_argb = 0; } -#if defined(HAS_SETROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - ARGBSetRows_NEON(dst_argb, value, width, dst_stride_argb, height); - return 0; + +#if defined(HAS_ARGBSETROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBSetRow = ARGBSetRow_Any_NEON; + if (IS_ALIGNED(width, 4)) { + ARGBSetRow = ARGBSetRow_NEON; + } } #endif -#if defined(HAS_SETROW_X86) +#if defined(HAS_ARGBSETROW_X86) if (TestCpuFlag(kCpuHasX86)) { - ARGBSetRows_X86(dst_argb, value, width, dst_stride_argb, height); - return 0; + ARGBSetRow = ARGBSetRow_X86; } #endif - ARGBSetRows_C(dst_argb, value, width, dst_stride_argb, height); + + // Set plane + for (y = 0; y < height; ++y) { + ARGBSetRow(dst_argb, value, width); + dst_argb += dst_stride_argb; + } return 0; } @@ -1196,18 +1289,8 @@ int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, height = 1; src_stride_argb = dst_stride_argb = 0; } -#if defined(HAS_ARGBATTENUATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - ARGBAttenuateRow = ARGBAttenuateRow_Any_SSE2; - if (IS_ALIGNED(width, 4)) { - ARGBAttenuateRow = ARGBAttenuateRow_SSE2; - } - } -#endif #if defined(HAS_ARGBATTENUATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3; if (IS_ALIGNED(width, 4)) { ARGBAttenuateRow = ARGBAttenuateRow_SSSE3; @@ -1215,7 +1298,7 @@ int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBATTENUATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2; if (IS_ALIGNED(width, 8)) { ARGBAttenuateRow = ARGBAttenuateRow_AVX2; @@ -1223,7 +1306,7 @@ int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBATTENUATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON; if (IS_ALIGNED(width, 8)) { ARGBAttenuateRow = ARGBAttenuateRow_NEON; @@ -1263,7 +1346,7 @@ int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb = 0; } #if defined(HAS_ARGBUNATTENUATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBUnattenuateRow = ARGBUnattenuateRow_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBUnattenuateRow = ARGBUnattenuateRow_SSE2; @@ -1271,7 +1354,7 @@ int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, } #endif #if defined(HAS_ARGBUNATTENUATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBUnattenuateRow = ARGBUnattenuateRow_Any_AVX2; if (IS_ALIGNED(width, 8)) { ARGBUnattenuateRow = ARGBUnattenuateRow_AVX2; @@ -1312,12 +1395,11 @@ int ARGBGrayTo(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb = 0; } #if defined(HAS_ARGBGRAYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) { ARGBGrayRow = ARGBGrayRow_SSSE3; } -#elif defined(HAS_ARGBGRAYROW_NEON) +#endif +#if defined(HAS_ARGBGRAYROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBGrayRow = ARGBGrayRow_NEON; } @@ -1350,11 +1432,11 @@ int ARGBGray(uint8* dst_argb, int dst_stride_argb, dst_stride_argb = 0; } #if defined(HAS_ARGBGRAYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) { ARGBGrayRow = ARGBGrayRow_SSSE3; } -#elif defined(HAS_ARGBGRAYROW_NEON) +#endif +#if defined(HAS_ARGBGRAYROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBGrayRow = ARGBGrayRow_NEON; } @@ -1383,11 +1465,11 @@ int ARGBSepia(uint8* dst_argb, int dst_stride_argb, dst_stride_argb = 0; } #if defined(HAS_ARGBSEPIAROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) { ARGBSepiaRow = ARGBSepiaRow_SSSE3; } -#elif defined(HAS_ARGBSEPIAROW_NEON) +#endif +#if defined(HAS_ARGBSEPIAROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBSepiaRow = ARGBSepiaRow_NEON; } @@ -1425,11 +1507,11 @@ int ARGBColorMatrix(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb = 0; } #if defined(HAS_ARGBCOLORMATRIXROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) { ARGBColorMatrixRow = ARGBColorMatrixRow_SSSE3; } -#elif defined(HAS_ARGBCOLORMATRIXROW_NEON) +#endif +#if defined(HAS_ARGBCOLORMATRIXROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBColorMatrixRow = ARGBColorMatrixRow_NEON; } @@ -1568,11 +1650,11 @@ int ARGBQuantize(uint8* dst_argb, int dst_stride_argb, dst_stride_argb = 0; } #if defined(HAS_ARGBQUANTIZEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4)) { ARGBQuantizeRow = ARGBQuantizeRow_SSE2; } -#elif defined(HAS_ARGBQUANTIZEROW_NEON) +#endif +#if defined(HAS_ARGBQUANTIZEROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBQuantizeRow = ARGBQuantizeRow_NEON; } @@ -1743,12 +1825,11 @@ int ARGBShade(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb = 0; } #if defined(HAS_ARGBSHADEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4)) { ARGBShadeRow = ARGBShadeRow_SSE2; } -#elif defined(HAS_ARGBSHADEROW_NEON) +#endif +#if defined(HAS_ARGBSHADEROW_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { ARGBShadeRow = ARGBShadeRow_NEON; } @@ -1762,91 +1843,121 @@ int ARGBShade(const uint8* src_argb, int src_stride_argb, return 0; } +// Interpolate 2 planes by specified amount (0 to 255). +LIBYUV_API +int InterpolatePlane(const uint8* src0, int src_stride0, + const uint8* src1, int src_stride1, + uint8* dst, int dst_stride, + int width, int height, int interpolation) { + int y; + void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) = InterpolateRow_C; + if (!src0 || !src1 || !dst || width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst = dst + (height - 1) * dst_stride; + dst_stride = -dst_stride; + } + // Coalesce rows. + if (src_stride0 == width && + src_stride1 == width && + dst_stride == width) { + width *= height; + height = 1; + src_stride0 = src_stride1 = dst_stride = 0; + } +#if defined(HAS_INTERPOLATEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + InterpolateRow = InterpolateRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_SSSE3; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + InterpolateRow = InterpolateRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + InterpolateRow = InterpolateRow_AVX2; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + InterpolateRow = InterpolateRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_NEON; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && + IS_ALIGNED(src0, 4) && IS_ALIGNED(src_stride0, 4) && + IS_ALIGNED(src1, 4) && IS_ALIGNED(src_stride1, 4) && + IS_ALIGNED(dst, 4) && IS_ALIGNED(dst_stride, 4) && + IS_ALIGNED(width, 4)) { + InterpolateRow = InterpolateRow_MIPS_DSPR2; + } +#endif + + for (y = 0; y < height; ++y) { + InterpolateRow(dst, src0, src1 - src0, + width, interpolation); + src0 += src_stride0; + src1 += src_stride1; + dst += dst_stride; + } + return 0; +} + // Interpolate 2 ARGB images by specified amount (0 to 255). LIBYUV_API int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0, const uint8* src_argb1, int src_stride_argb1, uint8* dst_argb, int dst_stride_argb, int width, int height, int interpolation) { - int y; - void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) = InterpolateRow_C; - if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { + return InterpolatePlane(src_argb0, src_stride_argb0, + src_argb1, src_stride_argb1, + dst_argb, dst_stride_argb, + width * 4, height, interpolation); +} + +// Interpolate 2 YUV images by specified amount (0 to 255). +LIBYUV_API +int I420Interpolate(const uint8* src0_y, int src0_stride_y, + const uint8* src0_u, int src0_stride_u, + const uint8* src0_v, int src0_stride_v, + const uint8* src1_y, int src1_stride_y, + const uint8* src1_u, int src1_stride_u, + const uint8* src1_v, int src1_stride_v, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height, int interpolation) { + int halfwidth = (width + 1) >> 1; + int halfheight = (height + 1) >> 1; + if (!src0_y || !src0_u || !src0_v || + !src1_y || !src1_u || !src1_v || + !dst_y || !dst_u || !dst_v || + width <= 0 || height == 0) { return -1; } - // Negative height means invert the image. - if (height < 0) { - height = -height; - dst_argb = dst_argb + (height - 1) * dst_stride_argb; - dst_stride_argb = -dst_stride_argb; - } - // Coalesce rows. - if (src_stride_argb0 == width * 4 && - src_stride_argb1 == width * 4 && - dst_stride_argb == width * 4) { - width *= height; - height = 1; - src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; - } -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) && - IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif -#if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) { - InterpolateRow = InterpolateRow_Any_SSSE3; - if (IS_ALIGNED(width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) && - IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } - } - } -#endif -#if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { - InterpolateRow = InterpolateRow_Any_AVX2; - if (IS_ALIGNED(width, 8)) { - InterpolateRow = InterpolateRow_AVX2; - } - } -#endif -#if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 4) { - InterpolateRow = InterpolateRow_Any_NEON; - if (IS_ALIGNED(width, 4)) { - InterpolateRow = InterpolateRow_NEON; - } - } -#endif -#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && width >= 1 && - IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) && - IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) && - IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { - ScaleARGBFilterRows = InterpolateRow_MIPS_DSPR2; - } -#endif - - for (y = 0; y < height; ++y) { - InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0, - width * 4, interpolation); - src_argb0 += src_stride_argb0; - src_argb1 += src_stride_argb1; - dst_argb += dst_stride_argb; - } + InterpolatePlane(src0_y, src0_stride_y, + src1_y, src1_stride_y, + dst_y, dst_stride_y, + width, height, interpolation); + InterpolatePlane(src0_u, src0_stride_u, + src1_u, src1_stride_u, + dst_u, dst_stride_u, + halfwidth, halfheight, interpolation); + InterpolatePlane(src0_v, src0_stride_v, + src1_v, src1_stride_v, + dst_v, dst_stride_v, + halfwidth, halfheight, interpolation); return 0; } @@ -1857,7 +1968,7 @@ int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, const uint8* shuffler, int width, int height) { int y; void (*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb, - const uint8* shuffler, int pix) = ARGBShuffleRow_C; + const uint8* shuffler, int width) = ARGBShuffleRow_C; if (!src_bgra || !dst_argb || width <= 0 || height == 0) { return -1; @@ -1876,7 +1987,7 @@ int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, src_stride_bgra = dst_stride_argb = 0; } #if defined(HAS_ARGBSHUFFLEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { + if (TestCpuFlag(kCpuHasSSE2)) { ARGBShuffleRow = ARGBShuffleRow_Any_SSE2; if (IS_ALIGNED(width, 4)) { ARGBShuffleRow = ARGBShuffleRow_SSE2; @@ -1884,19 +1995,15 @@ int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, } #endif #if defined(HAS_ARGBSHUFFLEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { ARGBShuffleRow = ARGBShuffleRow_Any_SSSE3; if (IS_ALIGNED(width, 8)) { - ARGBShuffleRow = ARGBShuffleRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - ARGBShuffleRow = ARGBShuffleRow_SSSE3; - } + ARGBShuffleRow = ARGBShuffleRow_SSSE3; } } #endif #if defined(HAS_ARGBSHUFFLEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { + if (TestCpuFlag(kCpuHasAVX2)) { ARGBShuffleRow = ARGBShuffleRow_Any_AVX2; if (IS_ALIGNED(width, 16)) { ARGBShuffleRow = ARGBShuffleRow_AVX2; @@ -1904,7 +2011,7 @@ int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, } #endif #if defined(HAS_ARGBSHUFFLEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 4) { + if (TestCpuFlag(kCpuHasNEON)) { ARGBShuffleRow = ARGBShuffleRow_Any_NEON; if (IS_ALIGNED(width, 4)) { ARGBShuffleRow = ARGBShuffleRow_NEON; @@ -1928,8 +2035,8 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, const uint8* src_sobely, uint8* dst, int width)) { int y; - void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) = ARGBToBayerGGRow_C; + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_g, int width) = + ARGBToYJRow_C; void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1, uint8* dst_sobely, int width) = SobelYRow_C; void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1, @@ -1945,33 +2052,32 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, src_argb = src_argb + (height - 1) * src_stride_argb; src_stride_argb = -src_stride_argb; } - // ARGBToBayer used to select G channel from ARGB. -#if defined(HAS_ARGBTOBAYERGGROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerGGRow_SSE2; + +#if defined(HAS_ARGBTOYJROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + ARGBToYJRow = ARGBToYJRow_SSSE3; } } #endif -#if defined(HAS_ARGBTOBAYERROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && width >= 8 && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { - ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; - if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerRow_SSSE3; +#if defined(HAS_ARGBTOYJROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBToYJRow = ARGBToYJRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + ARGBToYJRow = ARGBToYJRow_AVX2; } } #endif -#if defined(HAS_ARGBTOBAYERGGROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && width >= 8) { - ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON; +#if defined(HAS_ARGBTOYJROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBToYJRow = ARGBToYJRow_Any_NEON; if (IS_ALIGNED(width, 8)) { - ARGBToBayerRow = ARGBToBayerGGRow_NEON; + ARGBToYJRow = ARGBToYJRow_NEON; } } #endif + #if defined(HAS_SOBELYROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { SobelYRow = SobelYRow_SSE2; @@ -1994,7 +2100,7 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, #endif { // 3 rows with edges before/after. - const int kRowSize = (width + kEdge + 15) & ~15; + const int kRowSize = (width + kEdge + 31) & ~31; align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge)); uint8* row_sobelx = rows; uint8* row_sobely = rows + kRowSize; @@ -2004,20 +2110,20 @@ static int ARGBSobelize(const uint8* src_argb, int src_stride_argb, uint8* row_y0 = row_y + kEdge; uint8* row_y1 = row_y0 + kRowSize; uint8* row_y2 = row_y1 + kRowSize; - ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width); + ARGBToYJRow(src_argb, row_y0, width); row_y0[-1] = row_y0[0]; memset(row_y0 + width, row_y0[width - 1], 16); // Extrude 16 for valgrind. - ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width); + ARGBToYJRow(src_argb, row_y1, width); row_y1[-1] = row_y1[0]; memset(row_y1 + width, row_y1[width - 1], 16); memset(row_y2 + width, 0, 16); for (y = 0; y < height; ++y) { - // Convert next row of ARGB to Y. + // Convert next row of ARGB to G. if (y < (height - 1)) { src_argb += src_stride_argb; } - ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width); + ARGBToYJRow(src_argb, row_y2, width); row_y2[-1] = row_y2[0]; row_y2[width] = row_y2[width - 1]; @@ -2048,14 +2154,19 @@ int ARGBSobel(const uint8* src_argb, int src_stride_argb, void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width) = SobelRow_C; #if defined(HAS_SOBELROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - SobelRow = SobelRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + SobelRow = SobelRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + SobelRow = SobelRow_SSE2; + } } #endif #if defined(HAS_SOBELROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { - SobelRow = SobelRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + SobelRow = SobelRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + SobelRow = SobelRow_NEON; + } } #endif return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, @@ -2070,14 +2181,19 @@ int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_, int width) = SobelToPlaneRow_C; #if defined(HAS_SOBELTOPLANEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && - IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { - SobelToPlaneRow = SobelToPlaneRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + SobelToPlaneRow = SobelToPlaneRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + SobelToPlaneRow = SobelToPlaneRow_SSE2; + } } #endif #if defined(HAS_SOBELTOPLANEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { - SobelToPlaneRow = SobelToPlaneRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + SobelToPlaneRow = SobelToPlaneRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + SobelToPlaneRow = SobelToPlaneRow_NEON; + } } #endif return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y, @@ -2093,14 +2209,19 @@ int ARGBSobelXY(const uint8* src_argb, int src_stride_argb, void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width) = SobelXYRow_C; #if defined(HAS_SOBELXYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - SobelXYRow = SobelXYRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + SobelXYRow = SobelXYRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + SobelXYRow = SobelXYRow_SSE2; + } } #endif #if defined(HAS_SOBELXYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { - SobelXYRow = SobelXYRow_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + SobelXYRow = SobelXYRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + SobelXYRow = SobelXYRow_NEON; + } } #endif return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, @@ -2218,16 +2339,19 @@ int ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb, src_stride_argb = dst_stride_argb = 0; } #if defined(HAS_ARGBCOPYALPHAROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) && - IS_ALIGNED(width, 8)) { - ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBCopyAlphaRow = ARGBCopyAlphaRow_Any_SSE2; + if (IS_ALIGNED(width, 8)) { + ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2; + } } #endif #if defined(HAS_ARGBCOPYALPHAROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) { - ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2; + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBCopyAlphaRow = ARGBCopyAlphaRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2; + } } #endif @@ -2264,16 +2388,19 @@ int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, src_stride_y = dst_stride_argb = 0; } #if defined(HAS_ARGBCOPYYTOALPHAROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) && - IS_ALIGNED(width, 8)) { - ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_Any_SSE2; + if (IS_ALIGNED(width, 8)) { + ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2; + } } #endif #if defined(HAS_ARGBCOPYYTOALPHAROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) { - ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2; + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2; + } } #endif @@ -2285,6 +2412,198 @@ int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, return 0; } +LIBYUV_API +int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2, + uint8* dst_y, int dst_stride_y, + uint8* dst_uv, int dst_stride_uv, + int width, int height) { + int y; + int halfwidth = (width + 1) >> 1; + void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width) = SplitUVRow_C; + void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) = InterpolateRow_C; + if (!src_yuy2 || + !dst_y || !dst_uv || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; + src_stride_yuy2 = -src_stride_yuy2; + } +#if defined(HAS_SPLITUVROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + SplitUVRow = SplitUVRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + SplitUVRow = SplitUVRow_SSE2; + } + } +#endif +#if defined(HAS_SPLITUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + SplitUVRow = SplitUVRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + SplitUVRow = SplitUVRow_AVX2; + } + } +#endif +#if defined(HAS_SPLITUVROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + SplitUVRow = SplitUVRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + SplitUVRow = SplitUVRow_NEON; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + InterpolateRow = InterpolateRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_SSSE3; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + InterpolateRow = InterpolateRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + InterpolateRow = InterpolateRow_AVX2; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + InterpolateRow = InterpolateRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_NEON; + } + } +#endif + + { + int awidth = halfwidth * 2; + // 2 rows of uv + align_buffer_64(rows, awidth * 2); + + for (y = 0; y < height - 1; y += 2) { + // Split Y from UV. + SplitUVRow(src_yuy2, dst_y, rows, awidth); + SplitUVRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, + rows + awidth, awidth); + InterpolateRow(dst_uv, rows, awidth, awidth, 128); + src_yuy2 += src_stride_yuy2 * 2; + dst_y += dst_stride_y * 2; + dst_uv += dst_stride_uv; + } + if (height & 1) { + // Split Y from UV. + SplitUVRow(src_yuy2, dst_y, dst_uv, awidth); + } + free_aligned_buffer_64(rows); + } + return 0; +} + +LIBYUV_API +int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, + uint8* dst_y, int dst_stride_y, + uint8* dst_uv, int dst_stride_uv, + int width, int height) { + int y; + int halfwidth = (width + 1) >> 1; + void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width) = SplitUVRow_C; + void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) = InterpolateRow_C; + if (!src_uyvy || + !dst_y || !dst_uv || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; + src_stride_uyvy = -src_stride_uyvy; + } +#if defined(HAS_SPLITUVROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + SplitUVRow = SplitUVRow_Any_SSE2; + if (IS_ALIGNED(width, 16)) { + SplitUVRow = SplitUVRow_SSE2; + } + } +#endif +#if defined(HAS_SPLITUVROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + SplitUVRow = SplitUVRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + SplitUVRow = SplitUVRow_AVX2; + } + } +#endif +#if defined(HAS_SPLITUVROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + SplitUVRow = SplitUVRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + SplitUVRow = SplitUVRow_NEON; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + InterpolateRow = InterpolateRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_SSSE3; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + InterpolateRow = InterpolateRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + InterpolateRow = InterpolateRow_AVX2; + } + } +#endif +#if defined(HAS_INTERPOLATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + InterpolateRow = InterpolateRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + InterpolateRow = InterpolateRow_NEON; + } + } +#endif + + { + int awidth = halfwidth * 2; + // 2 rows of uv + align_buffer_64(rows, awidth * 2); + + for (y = 0; y < height - 1; y += 2) { + // Split Y from UV. + SplitUVRow(src_uyvy, rows, dst_y, awidth); + SplitUVRow(src_uyvy + src_stride_uyvy, rows + awidth, + dst_y + dst_stride_y, awidth); + InterpolateRow(dst_uv, rows, awidth, awidth, 128); + src_uyvy += src_stride_uyvy * 2; + dst_y += dst_stride_y * 2; + dst_uv += dst_stride_uv; + } + if (height & 1) { + // Split Y from UV. + SplitUVRow(src_uyvy, dst_uv, dst_y, awidth); + } + free_aligned_buffer_64(rows); + } + return 0; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/TMessagesProj/jni/libyuv/source/rotate.cc b/TMessagesProj/jni/libyuv/source/rotate.cc index fe0e72b1..31e04af9 100644 --- a/TMessagesProj/jni/libyuv/source/rotate.cc +++ b/TMessagesProj/jni/libyuv/source/rotate.cc @@ -13,6 +13,7 @@ #include "libyuv/cpu_id.h" #include "libyuv/convert.h" #include "libyuv/planar_functions.h" +#include "libyuv/rotate_row.h" #include "libyuv/row.h" #ifdef __cplusplus @@ -20,829 +21,39 @@ namespace libyuv { extern "C" { #endif -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -#if defined(__APPLE__) && defined(__i386__) -#define DECLARE_FUNCTION(name) \ - ".text \n" \ - ".private_extern _" #name " \n" \ - ".align 4,0x90 \n" \ -"_" #name ": \n" -#elif defined(__MINGW32__) || defined(__CYGWIN__) && defined(__i386__) -#define DECLARE_FUNCTION(name) \ - ".text \n" \ - ".align 4,0x90 \n" \ -"_" #name ": \n" -#else -#define DECLARE_FUNCTION(name) \ - ".text \n" \ - ".align 4,0x90 \n" \ -#name ": \n" -#endif -#endif - -#if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) -#define HAS_MIRRORROW_NEON -void MirrorRow_NEON(const uint8* src, uint8* dst, int width); -#define HAS_MIRRORROW_UV_NEON -void MirrorUVRow_NEON(const uint8* src, uint8* dst_a, uint8* dst_b, int width); -#define HAS_TRANSPOSE_WX8_NEON -void TransposeWx8_NEON(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width); -#define HAS_TRANSPOSE_UVWX8_NEON -void TransposeUVWx8_NEON(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int width); -#elif !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ - (defined(__aarch64__) || defined(LIBYUV_NEON)) -// #define HAS_MIRRORROW_NEON -// void MirrorRow_NEON(const uint8* src, uint8* dst, int width); -// #define HAS_MIRRORROW_UV_NEON -// void MirrorUVRow_NEON(const uint8* src, uint8* dst_a, uint8* dst_b, int width); -// #define HAS_TRANSPOSE_WX8_NEON -// void TransposeWx8_NEON(const uint8* src, int src_stride, -// uint8* dst, int dst_stride, int width); -// #define HAS_TRANSPOSE_UVWX8_NEON -// void TransposeUVWx8_NEON(const uint8* src, int src_stride, -// uint8* dst_a, int dst_stride_a, -// uint8* dst_b, int dst_stride_b, -// int width); -#endif // defined(__ARM_NEON__) - -#if !defined(LIBYUV_DISABLE_MIPS) && !defined(__native_client__) && \ - defined(__mips__) && \ - defined(__mips_dsp) && (__mips_dsp_rev >= 2) -#define HAS_TRANSPOSE_WX8_MIPS_DSPR2 -void TransposeWx8_MIPS_DSPR2(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width); - -void TransposeWx8_FAST_MIPS_DSPR2(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width); -#define HAS_TRANSPOSE_UVWx8_MIPS_DSPR2 -void TransposeUVWx8_MIPS_DSPR2(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int width); -#endif // defined(__mips__) - -#if !defined(LIBYUV_DISABLE_X86) && \ - defined(_M_IX86) && defined(_MSC_VER) -#define HAS_TRANSPOSE_WX8_SSSE3 -__declspec(naked) __declspec(align(16)) -static void TransposeWx8_SSSE3(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width) { - __asm { - push edi - push esi - push ebp - mov eax, [esp + 12 + 4] // src - mov edi, [esp + 12 + 8] // src_stride - mov edx, [esp + 12 + 12] // dst - mov esi, [esp + 12 + 16] // dst_stride - mov ecx, [esp + 12 + 20] // width - - // Read in the data from the source pointer. - // First round of bit swap. - align 4 - convertloop: - movq xmm0, qword ptr [eax] - lea ebp, [eax + 8] - movq xmm1, qword ptr [eax + edi] - lea eax, [eax + 2 * edi] - punpcklbw xmm0, xmm1 - movq xmm2, qword ptr [eax] - movdqa xmm1, xmm0 - palignr xmm1, xmm1, 8 - movq xmm3, qword ptr [eax + edi] - lea eax, [eax + 2 * edi] - punpcklbw xmm2, xmm3 - movdqa xmm3, xmm2 - movq xmm4, qword ptr [eax] - palignr xmm3, xmm3, 8 - movq xmm5, qword ptr [eax + edi] - punpcklbw xmm4, xmm5 - lea eax, [eax + 2 * edi] - movdqa xmm5, xmm4 - movq xmm6, qword ptr [eax] - palignr xmm5, xmm5, 8 - movq xmm7, qword ptr [eax + edi] - punpcklbw xmm6, xmm7 - mov eax, ebp - movdqa xmm7, xmm6 - palignr xmm7, xmm7, 8 - // Second round of bit swap. - punpcklwd xmm0, xmm2 - punpcklwd xmm1, xmm3 - movdqa xmm2, xmm0 - movdqa xmm3, xmm1 - palignr xmm2, xmm2, 8 - palignr xmm3, xmm3, 8 - punpcklwd xmm4, xmm6 - punpcklwd xmm5, xmm7 - movdqa xmm6, xmm4 - movdqa xmm7, xmm5 - palignr xmm6, xmm6, 8 - palignr xmm7, xmm7, 8 - // Third round of bit swap. - // Write to the destination pointer. - punpckldq xmm0, xmm4 - movq qword ptr [edx], xmm0 - movdqa xmm4, xmm0 - palignr xmm4, xmm4, 8 - movq qword ptr [edx + esi], xmm4 - lea edx, [edx + 2 * esi] - punpckldq xmm2, xmm6 - movdqa xmm6, xmm2 - palignr xmm6, xmm6, 8 - movq qword ptr [edx], xmm2 - punpckldq xmm1, xmm5 - movq qword ptr [edx + esi], xmm6 - lea edx, [edx + 2 * esi] - movdqa xmm5, xmm1 - movq qword ptr [edx], xmm1 - palignr xmm5, xmm5, 8 - punpckldq xmm3, xmm7 - movq qword ptr [edx + esi], xmm5 - lea edx, [edx + 2 * esi] - movq qword ptr [edx], xmm3 - movdqa xmm7, xmm3 - palignr xmm7, xmm7, 8 - sub ecx, 8 - movq qword ptr [edx + esi], xmm7 - lea edx, [edx + 2 * esi] - jg convertloop - - pop ebp - pop esi - pop edi - ret - } -} - -#define HAS_TRANSPOSE_UVWX8_SSE2 -__declspec(naked) __declspec(align(16)) -static void TransposeUVWx8_SSE2(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int w) { - __asm { - push ebx - push esi - push edi - push ebp - mov eax, [esp + 16 + 4] // src - mov edi, [esp + 16 + 8] // src_stride - mov edx, [esp + 16 + 12] // dst_a - mov esi, [esp + 16 + 16] // dst_stride_a - mov ebx, [esp + 16 + 20] // dst_b - mov ebp, [esp + 16 + 24] // dst_stride_b - mov ecx, esp - sub esp, 4 + 16 - and esp, ~15 - mov [esp + 16], ecx - mov ecx, [ecx + 16 + 28] // w - - align 4 - convertloop: - // Read in the data from the source pointer. - // First round of bit swap. - movdqa xmm0, [eax] - movdqa xmm1, [eax + edi] - lea eax, [eax + 2 * edi] - movdqa xmm7, xmm0 // use xmm7 as temp register. - punpcklbw xmm0, xmm1 - punpckhbw xmm7, xmm1 - movdqa xmm1, xmm7 - movdqa xmm2, [eax] - movdqa xmm3, [eax + edi] - lea eax, [eax + 2 * edi] - movdqa xmm7, xmm2 - punpcklbw xmm2, xmm3 - punpckhbw xmm7, xmm3 - movdqa xmm3, xmm7 - movdqa xmm4, [eax] - movdqa xmm5, [eax + edi] - lea eax, [eax + 2 * edi] - movdqa xmm7, xmm4 - punpcklbw xmm4, xmm5 - punpckhbw xmm7, xmm5 - movdqa xmm5, xmm7 - movdqa xmm6, [eax] - movdqa xmm7, [eax + edi] - lea eax, [eax + 2 * edi] - movdqa [esp], xmm5 // backup xmm5 - neg edi - movdqa xmm5, xmm6 // use xmm5 as temp register. - punpcklbw xmm6, xmm7 - punpckhbw xmm5, xmm7 - movdqa xmm7, xmm5 - lea eax, [eax + 8 * edi + 16] - neg edi - // Second round of bit swap. - movdqa xmm5, xmm0 - punpcklwd xmm0, xmm2 - punpckhwd xmm5, xmm2 - movdqa xmm2, xmm5 - movdqa xmm5, xmm1 - punpcklwd xmm1, xmm3 - punpckhwd xmm5, xmm3 - movdqa xmm3, xmm5 - movdqa xmm5, xmm4 - punpcklwd xmm4, xmm6 - punpckhwd xmm5, xmm6 - movdqa xmm6, xmm5 - movdqa xmm5, [esp] // restore xmm5 - movdqa [esp], xmm6 // backup xmm6 - movdqa xmm6, xmm5 // use xmm6 as temp register. - punpcklwd xmm5, xmm7 - punpckhwd xmm6, xmm7 - movdqa xmm7, xmm6 - // Third round of bit swap. - // Write to the destination pointer. - movdqa xmm6, xmm0 - punpckldq xmm0, xmm4 - punpckhdq xmm6, xmm4 - movdqa xmm4, xmm6 - movdqa xmm6, [esp] // restore xmm6 - movlpd qword ptr [edx], xmm0 - movhpd qword ptr [ebx], xmm0 - movlpd qword ptr [edx + esi], xmm4 - lea edx, [edx + 2 * esi] - movhpd qword ptr [ebx + ebp], xmm4 - lea ebx, [ebx + 2 * ebp] - movdqa xmm0, xmm2 // use xmm0 as the temp register. - punpckldq xmm2, xmm6 - movlpd qword ptr [edx], xmm2 - movhpd qword ptr [ebx], xmm2 - punpckhdq xmm0, xmm6 - movlpd qword ptr [edx + esi], xmm0 - lea edx, [edx + 2 * esi] - movhpd qword ptr [ebx + ebp], xmm0 - lea ebx, [ebx + 2 * ebp] - movdqa xmm0, xmm1 // use xmm0 as the temp register. - punpckldq xmm1, xmm5 - movlpd qword ptr [edx], xmm1 - movhpd qword ptr [ebx], xmm1 - punpckhdq xmm0, xmm5 - movlpd qword ptr [edx + esi], xmm0 - lea edx, [edx + 2 * esi] - movhpd qword ptr [ebx + ebp], xmm0 - lea ebx, [ebx + 2 * ebp] - movdqa xmm0, xmm3 // use xmm0 as the temp register. - punpckldq xmm3, xmm7 - movlpd qword ptr [edx], xmm3 - movhpd qword ptr [ebx], xmm3 - punpckhdq xmm0, xmm7 - sub ecx, 8 - movlpd qword ptr [edx + esi], xmm0 - lea edx, [edx + 2 * esi] - movhpd qword ptr [ebx + ebp], xmm0 - lea ebx, [ebx + 2 * ebp] - jg convertloop - - mov esp, [esp + 16] - pop ebp - pop edi - pop esi - pop ebx - ret - } -} -#elif !defined(LIBYUV_DISABLE_X86) && \ - (defined(__i386__) || (defined(__x86_64__) && !defined(__native_client__))) -#define HAS_TRANSPOSE_WX8_SSSE3 -static void TransposeWx8_SSSE3(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width) { - asm volatile ( - // Read in the data from the source pointer. - // First round of bit swap. - ".p2align 2 \n" - "1: \n" - "movq (%0),%%xmm0 \n" - "movq (%0,%3),%%xmm1 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "movq (%0),%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "palignr $0x8,%%xmm1,%%xmm1 \n" - "movq (%0,%3),%%xmm3 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "movdqa %%xmm2,%%xmm3 \n" - "movq (%0),%%xmm4 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "movq (%0,%3),%%xmm5 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "movq (%0),%%xmm6 \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq (%0,%3),%%xmm7 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "neg %3 \n" - "movdqa %%xmm6,%%xmm7 \n" - "lea 0x8(%0,%3,8),%0 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "neg %3 \n" - // Second round of bit swap. - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "palignr $0x8,%%xmm2,%%xmm2 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm4,%%xmm6 \n" - "movdqa %%xmm5,%%xmm7 \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - // Third round of bit swap. - // Write to the destination pointer. - "punpckldq %%xmm4,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "movdqa %%xmm0,%%xmm4 \n" - "palignr $0x8,%%xmm4,%%xmm4 \n" - "movq %%xmm4,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movdqa %%xmm2,%%xmm6 \n" - "movq %%xmm2,(%1) \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movq %%xmm6,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm1,%%xmm5 \n" - "movq %%xmm1,(%1) \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq %%xmm5,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movq %%xmm3,(%1) \n" - "movdqa %%xmm3,%%xmm7 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "sub $0x8,%2 \n" - "movq %%xmm7,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : "r"((intptr_t)(src_stride)), // %3 - "r"((intptr_t)(dst_stride)) // %4 - : "memory", "cc" - #if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" - #endif - ); -} - -#if !defined(LIBYUV_DISABLE_X86) && defined(__i386__) -#define HAS_TRANSPOSE_UVWX8_SSE2 -void TransposeUVWx8_SSE2(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int w); - asm ( - DECLARE_FUNCTION(TransposeUVWx8_SSE2) - "push %ebx \n" - "push %esi \n" - "push %edi \n" - "push %ebp \n" - "mov 0x14(%esp),%eax \n" - "mov 0x18(%esp),%edi \n" - "mov 0x1c(%esp),%edx \n" - "mov 0x20(%esp),%esi \n" - "mov 0x24(%esp),%ebx \n" - "mov 0x28(%esp),%ebp \n" - "mov %esp,%ecx \n" - "sub $0x14,%esp \n" - "and $0xfffffff0,%esp \n" - "mov %ecx,0x10(%esp) \n" - "mov 0x2c(%ecx),%ecx \n" - -"1: \n" - "movdqa (%eax),%xmm0 \n" - "movdqa (%eax,%edi,1),%xmm1 \n" - "lea (%eax,%edi,2),%eax \n" - "movdqa %xmm0,%xmm7 \n" - "punpcklbw %xmm1,%xmm0 \n" - "punpckhbw %xmm1,%xmm7 \n" - "movdqa %xmm7,%xmm1 \n" - "movdqa (%eax),%xmm2 \n" - "movdqa (%eax,%edi,1),%xmm3 \n" - "lea (%eax,%edi,2),%eax \n" - "movdqa %xmm2,%xmm7 \n" - "punpcklbw %xmm3,%xmm2 \n" - "punpckhbw %xmm3,%xmm7 \n" - "movdqa %xmm7,%xmm3 \n" - "movdqa (%eax),%xmm4 \n" - "movdqa (%eax,%edi,1),%xmm5 \n" - "lea (%eax,%edi,2),%eax \n" - "movdqa %xmm4,%xmm7 \n" - "punpcklbw %xmm5,%xmm4 \n" - "punpckhbw %xmm5,%xmm7 \n" - "movdqa %xmm7,%xmm5 \n" - "movdqa (%eax),%xmm6 \n" - "movdqa (%eax,%edi,1),%xmm7 \n" - "lea (%eax,%edi,2),%eax \n" - "movdqa %xmm5,(%esp) \n" - "neg %edi \n" - "movdqa %xmm6,%xmm5 \n" - "punpcklbw %xmm7,%xmm6 \n" - "punpckhbw %xmm7,%xmm5 \n" - "movdqa %xmm5,%xmm7 \n" - "lea 0x10(%eax,%edi,8),%eax \n" - "neg %edi \n" - "movdqa %xmm0,%xmm5 \n" - "punpcklwd %xmm2,%xmm0 \n" - "punpckhwd %xmm2,%xmm5 \n" - "movdqa %xmm5,%xmm2 \n" - "movdqa %xmm1,%xmm5 \n" - "punpcklwd %xmm3,%xmm1 \n" - "punpckhwd %xmm3,%xmm5 \n" - "movdqa %xmm5,%xmm3 \n" - "movdqa %xmm4,%xmm5 \n" - "punpcklwd %xmm6,%xmm4 \n" - "punpckhwd %xmm6,%xmm5 \n" - "movdqa %xmm5,%xmm6 \n" - "movdqa (%esp),%xmm5 \n" - "movdqa %xmm6,(%esp) \n" - "movdqa %xmm5,%xmm6 \n" - "punpcklwd %xmm7,%xmm5 \n" - "punpckhwd %xmm7,%xmm6 \n" - "movdqa %xmm6,%xmm7 \n" - "movdqa %xmm0,%xmm6 \n" - "punpckldq %xmm4,%xmm0 \n" - "punpckhdq %xmm4,%xmm6 \n" - "movdqa %xmm6,%xmm4 \n" - "movdqa (%esp),%xmm6 \n" - "movlpd %xmm0,(%edx) \n" - "movhpd %xmm0,(%ebx) \n" - "movlpd %xmm4,(%edx,%esi,1) \n" - "lea (%edx,%esi,2),%edx \n" - "movhpd %xmm4,(%ebx,%ebp,1) \n" - "lea (%ebx,%ebp,2),%ebx \n" - "movdqa %xmm2,%xmm0 \n" - "punpckldq %xmm6,%xmm2 \n" - "movlpd %xmm2,(%edx) \n" - "movhpd %xmm2,(%ebx) \n" - "punpckhdq %xmm6,%xmm0 \n" - "movlpd %xmm0,(%edx,%esi,1) \n" - "lea (%edx,%esi,2),%edx \n" - "movhpd %xmm0,(%ebx,%ebp,1) \n" - "lea (%ebx,%ebp,2),%ebx \n" - "movdqa %xmm1,%xmm0 \n" - "punpckldq %xmm5,%xmm1 \n" - "movlpd %xmm1,(%edx) \n" - "movhpd %xmm1,(%ebx) \n" - "punpckhdq %xmm5,%xmm0 \n" - "movlpd %xmm0,(%edx,%esi,1) \n" - "lea (%edx,%esi,2),%edx \n" - "movhpd %xmm0,(%ebx,%ebp,1) \n" - "lea (%ebx,%ebp,2),%ebx \n" - "movdqa %xmm3,%xmm0 \n" - "punpckldq %xmm7,%xmm3 \n" - "movlpd %xmm3,(%edx) \n" - "movhpd %xmm3,(%ebx) \n" - "punpckhdq %xmm7,%xmm0 \n" - "sub $0x8,%ecx \n" - "movlpd %xmm0,(%edx,%esi,1) \n" - "lea (%edx,%esi,2),%edx \n" - "movhpd %xmm0,(%ebx,%ebp,1) \n" - "lea (%ebx,%ebp,2),%ebx \n" - "jg 1b \n" - "mov 0x10(%esp),%esp \n" - "pop %ebp \n" - "pop %edi \n" - "pop %esi \n" - "pop %ebx \n" -#if defined(__native_client__) - "pop %ecx \n" - "and $0xffffffe0,%ecx \n" - "jmp *%ecx \n" -#else - "ret \n" -#endif -); -#elif !defined(LIBYUV_DISABLE_X86) && !defined(__native_client__) && \ - defined(__x86_64__) -// 64 bit version has enough registers to do 16x8 to 8x16 at a time. -#define HAS_TRANSPOSE_WX8_FAST_SSSE3 -static void TransposeWx8_FAST_SSSE3(const uint8* src, int src_stride, - uint8* dst, int dst_stride, int width) { - asm volatile ( - // Read in the data from the source pointer. - // First round of bit swap. - ".p2align 2 \n" -"1: \n" - "movdqa (%0),%%xmm0 \n" - "movdqa (%0,%3),%%xmm1 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm0,%%xmm8 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm8 \n" - "movdqa (%0),%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm8,%%xmm9 \n" - "palignr $0x8,%%xmm1,%%xmm1 \n" - "palignr $0x8,%%xmm9,%%xmm9 \n" - "movdqa (%0,%3),%%xmm3 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm2,%%xmm10 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "punpckhbw %%xmm3,%%xmm10 \n" - "movdqa %%xmm2,%%xmm3 \n" - "movdqa %%xmm10,%%xmm11 \n" - "movdqa (%0),%%xmm4 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "palignr $0x8,%%xmm11,%%xmm11 \n" - "movdqa (%0,%3),%%xmm5 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm4,%%xmm12 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "punpckhbw %%xmm5,%%xmm12 \n" - "movdqa %%xmm4,%%xmm5 \n" - "movdqa %%xmm12,%%xmm13 \n" - "movdqa (%0),%%xmm6 \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "palignr $0x8,%%xmm13,%%xmm13 \n" - "movdqa (%0,%3),%%xmm7 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm6,%%xmm14 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "punpckhbw %%xmm7,%%xmm14 \n" - "neg %3 \n" - "movdqa %%xmm6,%%xmm7 \n" - "movdqa %%xmm14,%%xmm15 \n" - "lea 0x10(%0,%3,8),%0 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - "neg %3 \n" - // Second round of bit swap. - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "palignr $0x8,%%xmm2,%%xmm2 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm4,%%xmm6 \n" - "movdqa %%xmm5,%%xmm7 \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "punpcklwd %%xmm10,%%xmm8 \n" - "punpcklwd %%xmm11,%%xmm9 \n" - "movdqa %%xmm8,%%xmm10 \n" - "movdqa %%xmm9,%%xmm11 \n" - "palignr $0x8,%%xmm10,%%xmm10 \n" - "palignr $0x8,%%xmm11,%%xmm11 \n" - "punpcklwd %%xmm14,%%xmm12 \n" - "punpcklwd %%xmm15,%%xmm13 \n" - "movdqa %%xmm12,%%xmm14 \n" - "movdqa %%xmm13,%%xmm15 \n" - "palignr $0x8,%%xmm14,%%xmm14 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - // Third round of bit swap. - // Write to the destination pointer. - "punpckldq %%xmm4,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "movdqa %%xmm0,%%xmm4 \n" - "palignr $0x8,%%xmm4,%%xmm4 \n" - "movq %%xmm4,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movdqa %%xmm2,%%xmm6 \n" - "movq %%xmm2,(%1) \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movq %%xmm6,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm1,%%xmm5 \n" - "movq %%xmm1,(%1) \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq %%xmm5,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movq %%xmm3,(%1) \n" - "movdqa %%xmm3,%%xmm7 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "movq %%xmm7,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm12,%%xmm8 \n" - "movq %%xmm8,(%1) \n" - "movdqa %%xmm8,%%xmm12 \n" - "palignr $0x8,%%xmm12,%%xmm12 \n" - "movq %%xmm12,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm14,%%xmm10 \n" - "movdqa %%xmm10,%%xmm14 \n" - "movq %%xmm10,(%1) \n" - "palignr $0x8,%%xmm14,%%xmm14 \n" - "punpckldq %%xmm13,%%xmm9 \n" - "movq %%xmm14,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm9,%%xmm13 \n" - "movq %%xmm9,(%1) \n" - "palignr $0x8,%%xmm13,%%xmm13 \n" - "movq %%xmm13,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm15,%%xmm11 \n" - "movq %%xmm11,(%1) \n" - "movdqa %%xmm11,%%xmm15 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - "sub $0x10,%2 \n" - "movq %%xmm15,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : "r"((intptr_t)(src_stride)), // %3 - "r"((intptr_t)(dst_stride)) // %4 - : "memory", "cc", - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" -); -} - -#define HAS_TRANSPOSE_UVWX8_SSE2 -static void TransposeUVWx8_SSE2(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int w) { - asm volatile ( - // Read in the data from the source pointer. - // First round of bit swap. - ".p2align 2 \n" -"1: \n" - "movdqa (%0),%%xmm0 \n" - "movdqa (%0,%4),%%xmm1 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm0,%%xmm8 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm8 \n" - "movdqa %%xmm8,%%xmm1 \n" - "movdqa (%0),%%xmm2 \n" - "movdqa (%0,%4),%%xmm3 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm2,%%xmm8 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "punpckhbw %%xmm3,%%xmm8 \n" - "movdqa %%xmm8,%%xmm3 \n" - "movdqa (%0),%%xmm4 \n" - "movdqa (%0,%4),%%xmm5 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm4,%%xmm8 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "punpckhbw %%xmm5,%%xmm8 \n" - "movdqa %%xmm8,%%xmm5 \n" - "movdqa (%0),%%xmm6 \n" - "movdqa (%0,%4),%%xmm7 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm6,%%xmm8 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "neg %4 \n" - "lea 0x10(%0,%4,8),%0 \n" - "punpckhbw %%xmm7,%%xmm8 \n" - "movdqa %%xmm8,%%xmm7 \n" - "neg %4 \n" - // Second round of bit swap. - "movdqa %%xmm0,%%xmm8 \n" - "movdqa %%xmm1,%%xmm9 \n" - "punpckhwd %%xmm2,%%xmm8 \n" - "punpckhwd %%xmm3,%%xmm9 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm8,%%xmm2 \n" - "movdqa %%xmm9,%%xmm3 \n" - "movdqa %%xmm4,%%xmm8 \n" - "movdqa %%xmm5,%%xmm9 \n" - "punpckhwd %%xmm6,%%xmm8 \n" - "punpckhwd %%xmm7,%%xmm9 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm8,%%xmm6 \n" - "movdqa %%xmm9,%%xmm7 \n" - // Third round of bit swap. - // Write to the destination pointer. - "movdqa %%xmm0,%%xmm8 \n" - "punpckldq %%xmm4,%%xmm0 \n" - "movlpd %%xmm0,(%1) \n" // Write back U channel - "movhpd %%xmm0,(%2) \n" // Write back V channel - "punpckhdq %%xmm4,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm2,%%xmm8 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movlpd %%xmm2,(%1) \n" - "movhpd %%xmm2,(%2) \n" - "punpckhdq %%xmm6,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm1,%%xmm8 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movlpd %%xmm1,(%1) \n" - "movhpd %%xmm1,(%2) \n" - "punpckhdq %%xmm5,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm3,%%xmm8 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movlpd %%xmm3,(%1) \n" - "movhpd %%xmm3,(%2) \n" - "punpckhdq %%xmm7,%%xmm8 \n" - "sub $0x8,%3 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst_a), // %1 - "+r"(dst_b), // %2 - "+r"(w) // %3 - : "r"((intptr_t)(src_stride)), // %4 - "r"((intptr_t)(dst_stride_a)), // %5 - "r"((intptr_t)(dst_stride_b)) // %6 - : "memory", "cc", - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9" -); -} -#endif -#endif - -static void TransposeWx8_C(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width) { - int i; - for (i = 0; i < width; ++i) { - dst[0] = src[0 * src_stride]; - dst[1] = src[1 * src_stride]; - dst[2] = src[2 * src_stride]; - dst[3] = src[3 * src_stride]; - dst[4] = src[4 * src_stride]; - dst[5] = src[5 * src_stride]; - dst[6] = src[6 * src_stride]; - dst[7] = src[7 * src_stride]; - ++src; - dst += dst_stride; - } -} - -static void TransposeWxH_C(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width, int height) { - int i; - for (i = 0; i < width; ++i) { - int j; - for (j = 0; j < height; ++j) { - dst[i * dst_stride + j] = src[j * src_stride + i]; - } - } -} - LIBYUV_API void TransposePlane(const uint8* src, int src_stride, uint8* dst, int dst_stride, int width, int height) { int i = height; void (*TransposeWx8)(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width) = TransposeWx8_C; -#if defined(HAS_TRANSPOSE_WX8_NEON) + uint8* dst, int dst_stride, int width) = TransposeWx8_C; +#if defined(HAS_TRANSPOSEWX8_NEON) if (TestCpuFlag(kCpuHasNEON)) { TransposeWx8 = TransposeWx8_NEON; } #endif -#if defined(HAS_TRANSPOSE_WX8_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8)) { - TransposeWx8 = TransposeWx8_SSSE3; +#if defined(HAS_TRANSPOSEWX8_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + TransposeWx8 = TransposeWx8_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + TransposeWx8 = TransposeWx8_SSSE3; + } } #endif -#if defined(HAS_TRANSPOSE_WX8_FAST_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && - IS_ALIGNED(width, 16) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16)) { - TransposeWx8 = TransposeWx8_FAST_SSSE3; +#if defined(HAS_TRANSPOSEWX8_FAST_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + TransposeWx8 = TransposeWx8_Fast_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + TransposeWx8 = TransposeWx8_Fast_SSSE3; + } } #endif -#if defined(HAS_TRANSPOSE_WX8_MIPS_DSPR2) +#if defined(HAS_TRANSPOSEWX8_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2)) { if (IS_ALIGNED(width, 4) && IS_ALIGNED(src, 4) && IS_ALIGNED(src_stride, 4)) { - TransposeWx8 = TransposeWx8_FAST_MIPS_DSPR2; + TransposeWx8 = TransposeWx8_Fast_MIPS_DSPR2; } else { TransposeWx8 = TransposeWx8_MIPS_DSPR2; } @@ -857,7 +68,9 @@ void TransposePlane(const uint8* src, int src_stride, i -= 8; } - TransposeWxH_C(src, src_stride, dst, dst_stride, width, i); + if (i > 0) { + TransposeWxH_C(src, src_stride, dst, dst_stride, width, i); + } } LIBYUV_API @@ -897,29 +110,30 @@ void RotatePlane180(const uint8* src, int src_stride, void (*MirrorRow)(const uint8* src, uint8* dst, int width) = MirrorRow_C; void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; #if defined(HAS_MIRRORROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { - MirrorRow = MirrorRow_NEON; - } -#endif -#if defined(HAS_MIRRORROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - MirrorRow = MirrorRow_SSE2; + if (TestCpuFlag(kCpuHasNEON)) { + MirrorRow = MirrorRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + MirrorRow = MirrorRow_NEON; + } } #endif #if defined(HAS_MIRRORROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - MirrorRow = MirrorRow_SSSE3; + if (TestCpuFlag(kCpuHasSSSE3)) { + MirrorRow = MirrorRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + MirrorRow = MirrorRow_SSSE3; + } } #endif #if defined(HAS_MIRRORROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 32)) { - MirrorRow = MirrorRow_AVX2; + if (TestCpuFlag(kCpuHasAVX2)) { + MirrorRow = MirrorRow_Any_AVX2; + if (IS_ALIGNED(width, 32)) { + MirrorRow = MirrorRow_AVX2; + } } #endif +// TODO(fbarchard): Mirror on mips handle unaligned memory. #if defined(HAS_MIRRORROW_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src, 4) && IS_ALIGNED(src_stride, 4) && @@ -927,21 +141,14 @@ void RotatePlane180(const uint8* src, int src_stride, MirrorRow = MirrorRow_MIPS_DSPR2; } #endif -#if defined(HAS_COPYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { - CopyRow = CopyRow_NEON; - } -#endif -#if defined(HAS_COPYROW_X86) - if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { - CopyRow = CopyRow_X86; - } -#endif #if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - CopyRow = CopyRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; + } +#endif +#if defined(HAS_COPYROW_AVX) + if (TestCpuFlag(kCpuHasAVX)) { + CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX; } #endif #if defined(HAS_COPYROW_ERMS) @@ -949,6 +156,11 @@ void RotatePlane180(const uint8* src, int src_stride, CopyRow = CopyRow_ERMS; } #endif +#if defined(HAS_COPYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON; + } +#endif #if defined(HAS_COPYROW_MIPS) if (TestCpuFlag(kCpuHasMIPS)) { CopyRow = CopyRow_MIPS; @@ -968,48 +180,6 @@ void RotatePlane180(const uint8* src, int src_stride, free_aligned_buffer_64(row); } -static void TransposeUVWx8_C(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int width) { - int i; - for (i = 0; i < width; ++i) { - dst_a[0] = src[0 * src_stride + 0]; - dst_b[0] = src[0 * src_stride + 1]; - dst_a[1] = src[1 * src_stride + 0]; - dst_b[1] = src[1 * src_stride + 1]; - dst_a[2] = src[2 * src_stride + 0]; - dst_b[2] = src[2 * src_stride + 1]; - dst_a[3] = src[3 * src_stride + 0]; - dst_b[3] = src[3 * src_stride + 1]; - dst_a[4] = src[4 * src_stride + 0]; - dst_b[4] = src[4 * src_stride + 1]; - dst_a[5] = src[5 * src_stride + 0]; - dst_b[5] = src[5 * src_stride + 1]; - dst_a[6] = src[6 * src_stride + 0]; - dst_b[6] = src[6 * src_stride + 1]; - dst_a[7] = src[7 * src_stride + 0]; - dst_b[7] = src[7 * src_stride + 1]; - src += 2; - dst_a += dst_stride_a; - dst_b += dst_stride_b; - } -} - -static void TransposeUVWxH_C(const uint8* src, int src_stride, - uint8* dst_a, int dst_stride_a, - uint8* dst_b, int dst_stride_b, - int width, int height) { - int i; - for (i = 0; i < width * 2; i += 2) { - int j; - for (j = 0; j < height; ++j) { - dst_a[j + ((i >> 1) * dst_stride_a)] = src[i + (j * src_stride)]; - dst_b[j + ((i >> 1) * dst_stride_b)] = src[i + (j * src_stride) + 1]; - } - } -} - LIBYUV_API void TransposeUV(const uint8* src, int src_stride, uint8* dst_a, int dst_stride_a, @@ -1020,17 +190,20 @@ void TransposeUV(const uint8* src, int src_stride, uint8* dst_a, int dst_stride_a, uint8* dst_b, int dst_stride_b, int width) = TransposeUVWx8_C; -#if defined(HAS_TRANSPOSE_UVWX8_NEON) +#if defined(HAS_TRANSPOSEUVWX8_NEON) if (TestCpuFlag(kCpuHasNEON)) { TransposeUVWx8 = TransposeUVWx8_NEON; } -#elif defined(HAS_TRANSPOSE_UVWX8_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(width, 8) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16)) { - TransposeUVWx8 = TransposeUVWx8_SSE2; +#endif +#if defined(HAS_TRANSPOSEUVWX8_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + TransposeUVWx8 = TransposeUVWx8_Any_SSE2; + if (IS_ALIGNED(width, 8)) { + TransposeUVWx8 = TransposeUVWx8_SSE2; + } } -#elif defined(HAS_TRANSPOSE_UVWx8_MIPS_DSPR2) +#endif +#if defined(HAS_TRANSPOSEUVWX8_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 2) && IS_ALIGNED(src, 4) && IS_ALIGNED(src_stride, 4)) { TransposeUVWx8 = TransposeUVWx8_MIPS_DSPR2; @@ -1049,10 +222,12 @@ void TransposeUV(const uint8* src, int src_stride, i -= 8; } - TransposeUVWxH_C(src, src_stride, - dst_a, dst_stride_a, - dst_b, dst_stride_b, - width, i); + if (i > 0) { + TransposeUVWxH_C(src, src_stride, + dst_a, dst_stride_a, + dst_b, dst_stride_b, + width, i); + } } LIBYUV_API @@ -1098,12 +273,13 @@ void RotateUV180(const uint8* src, int src_stride, if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { MirrorRowUV = MirrorUVRow_NEON; } -#elif defined(HAS_MIRRORROW_UV_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16)) { +#endif +#if defined(HAS_MIRRORROW_UV_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16)) { MirrorRowUV = MirrorUVRow_SSSE3; } -#elif defined(HAS_MIRRORUVROW_MIPS_DSPR2) +#endif +#if defined(HAS_MIRRORUVROW_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src, 4) && IS_ALIGNED(src_stride, 4)) { MirrorRowUV = MirrorUVRow_MIPS_DSPR2; diff --git a/TMessagesProj/jni/libyuv/source/rotate_argb.cc b/TMessagesProj/jni/libyuv/source/rotate_argb.cc index ab0f9ce0..787c0ad1 100644 --- a/TMessagesProj/jni/libyuv/source/rotate_argb.cc +++ b/TMessagesProj/jni/libyuv/source/rotate_argb.cc @@ -27,36 +27,31 @@ extern "C" { (defined(__x86_64__) && !defined(__native_client__)) || defined(__i386__)) #define HAS_SCALEARGBROWDOWNEVEN_SSE2 void ScaleARGBRowDownEven_SSE2(const uint8* src_ptr, int src_stride, - int src_stepx, - uint8* dst_ptr, int dst_width); + int src_stepx, uint8* dst_ptr, int dst_width); #endif #if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) + (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) #define HAS_SCALEARGBROWDOWNEVEN_NEON void ScaleARGBRowDownEven_NEON(const uint8* src_ptr, int src_stride, - int src_stepx, - uint8* dst_ptr, int dst_width); + int src_stepx, uint8* dst_ptr, int dst_width); #endif void ScaleARGBRowDownEven_C(const uint8* src_ptr, int, - int src_stepx, - uint8* dst_ptr, int dst_width); + int src_stepx, uint8* dst_ptr, int dst_width); static void ARGBTranspose(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width, int height) { + uint8* dst, int dst_stride, int width, int height) { int i; int src_pixel_step = src_stride >> 2; void (*ScaleARGBRowDownEven)(const uint8* src_ptr, int src_stride, int src_step, uint8* dst_ptr, int dst_width) = ScaleARGBRowDownEven_C; #if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(height, 4) && // Width of dest. - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(height, 4)) { // Width of dest. ScaleARGBRowDownEven = ScaleARGBRowDownEven_SSE2; } -#elif defined(HAS_SCALEARGBROWDOWNEVEN_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(height, 4) && // Width of dest. - IS_ALIGNED(src, 4)) { +#endif +#if defined(HAS_SCALEARGBROWDOWNEVEN_NEON) + if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(height, 4)) { // Width of dest. ScaleARGBRowDownEven = ScaleARGBRowDownEven_NEON; } #endif @@ -69,8 +64,7 @@ static void ARGBTranspose(const uint8* src, int src_stride, } void ARGBRotate90(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width, int height) { + uint8* dst, int dst_stride, int width, int height) { // Rotate by 90 is a ARGBTranspose with the source read // from bottom to top. So set the source pointer to the end // of the buffer and flip the sign of the source stride. @@ -80,8 +74,7 @@ void ARGBRotate90(const uint8* src, int src_stride, } void ARGBRotate270(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width, int height) { + uint8* dst, int dst_stride, int width, int height) { // Rotate by 270 is a ARGBTranspose with the destination written // from bottom to top. So set the destination pointer to the end // of the buffer and flip the sign of the destination stride. @@ -91,8 +84,7 @@ void ARGBRotate270(const uint8* src, int src_stride, } void ARGBRotate180(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width, int height) { + uint8* dst, int dst_stride, int width, int height) { // Swap first and last row and mirror the content. Uses a temporary row. align_buffer_64(row, width * 4); const uint8* src_bot = src + src_stride * (height - 1); @@ -102,38 +94,38 @@ void ARGBRotate180(const uint8* src, int src_stride, void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) = ARGBMirrorRow_C; void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; -#if defined(HAS_ARGBMIRRORROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - ARGBMirrorRow = ARGBMirrorRow_SSSE3; +#if defined(HAS_ARGBMIRRORROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ARGBMirrorRow = ARGBMirrorRow_Any_NEON; + if (IS_ALIGNED(width, 4)) { + ARGBMirrorRow = ARGBMirrorRow_NEON; + } + } +#endif +#if defined(HAS_ARGBMIRRORROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ARGBMirrorRow = ARGBMirrorRow_Any_SSE2; + if (IS_ALIGNED(width, 4)) { + ARGBMirrorRow = ARGBMirrorRow_SSE2; + } } #endif #if defined(HAS_ARGBMIRRORROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 8)) { - ARGBMirrorRow = ARGBMirrorRow_AVX2; - } -#endif -#if defined(HAS_ARGBMIRRORROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) { - ARGBMirrorRow = ARGBMirrorRow_NEON; - } -#endif -#if defined(HAS_COPYROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width * 4, 32)) { - CopyRow = CopyRow_NEON; - } -#endif -#if defined(HAS_COPYROW_X86) - if (TestCpuFlag(kCpuHasX86)) { - CopyRow = CopyRow_X86; + if (TestCpuFlag(kCpuHasAVX2)) { + ARGBMirrorRow = ARGBMirrorRow_Any_AVX2; + if (IS_ALIGNED(width, 8)) { + ARGBMirrorRow = ARGBMirrorRow_AVX2; + } } #endif #if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width * 4, 32) && - IS_ALIGNED(src, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) { - CopyRow = CopyRow_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + CopyRow = IS_ALIGNED(width * 4, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; + } +#endif +#if defined(HAS_COPYROW_AVX) + if (TestCpuFlag(kCpuHasAVX)) { + CopyRow = IS_ALIGNED(width * 4, 64) ? CopyRow_AVX : CopyRow_Any_AVX; } #endif #if defined(HAS_COPYROW_ERMS) @@ -141,6 +133,11 @@ void ARGBRotate180(const uint8* src, int src_stride, CopyRow = CopyRow_ERMS; } #endif +#if defined(HAS_COPYROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + CopyRow = IS_ALIGNED(width * 4, 32) ? CopyRow_NEON : CopyRow_Any_NEON; + } +#endif #if defined(HAS_COPYROW_MIPS) if (TestCpuFlag(kCpuHasMIPS)) { CopyRow = CopyRow_MIPS; @@ -162,8 +159,7 @@ void ARGBRotate180(const uint8* src, int src_stride, LIBYUV_API int ARGBRotate(const uint8* src_argb, int src_stride_argb, - uint8* dst_argb, int dst_stride_argb, - int width, int height, + uint8* dst_argb, int dst_stride_argb, int width, int height, enum RotationMode mode) { if (!src_argb || width <= 0 || height == 0 || !dst_argb) { return -1; diff --git a/TMessagesProj/jni/libyuv/source/rotate_mips.cc b/TMessagesProj/jni/libyuv/source/rotate_mips.cc index 70770fd0..efe6bd90 100644 --- a/TMessagesProj/jni/libyuv/source/rotate_mips.cc +++ b/TMessagesProj/jni/libyuv/source/rotate_mips.cc @@ -9,6 +9,7 @@ */ #include "libyuv/row.h" +#include "libyuv/rotate_row.h" #include "libyuv/basic_types.h" @@ -22,8 +23,7 @@ extern "C" { (_MIPS_SIM == _MIPS_SIM_ABI32) void TransposeWx8_MIPS_DSPR2(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width) { + uint8* dst, int dst_stride, int width) { __asm__ __volatile__ ( ".set push \n" ".set noreorder \n" @@ -106,9 +106,8 @@ void TransposeWx8_MIPS_DSPR2(const uint8* src, int src_stride, ); } -void TransposeWx8_FAST_MIPS_DSPR2(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width) { +void TransposeWx8_Fast_MIPS_DSPR2(const uint8* src, int src_stride, + uint8* dst, int dst_stride, int width) { __asm__ __volatile__ ( ".set noat \n" ".set push \n" diff --git a/TMessagesProj/jni/libyuv/source/rotate_neon.cc b/TMessagesProj/jni/libyuv/source/rotate_neon.cc index d354e11f..9e4ecd80 100644 --- a/TMessagesProj/jni/libyuv/source/rotate_neon.cc +++ b/TMessagesProj/jni/libyuv/source/rotate_neon.cc @@ -9,6 +9,7 @@ */ #include "libyuv/row.h" +#include "libyuv/rotate_row.h" #include "libyuv/basic_types.h" @@ -17,7 +18,8 @@ namespace libyuv { extern "C" { #endif -#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) +#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \ + !defined(__aarch64__) static uvec8 kVTbl4x4Transpose = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; @@ -33,7 +35,6 @@ void TransposeWx8_NEON(const uint8* src, int src_stride, "sub %5, #8 \n" // handle 8x8 blocks. this should be the majority of the plane - ".p2align 2 \n" "1: \n" "mov %0, %1 \n" @@ -254,7 +255,6 @@ void TransposeUVWx8_NEON(const uint8* src, int src_stride, "sub %7, #8 \n" // handle 8x8 blocks. this should be the majority of the plane - ".p2align 2 \n" "1: \n" "mov %0, %1 \n" @@ -525,7 +525,7 @@ void TransposeUVWx8_NEON(const uint8* src, int src_stride, "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11" ); } -#endif +#endif // defined(__ARM_NEON__) && !defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/rotate_neon64.cc b/TMessagesProj/jni/libyuv/source/rotate_neon64.cc index b080a2c6..f52c082b 100644 --- a/TMessagesProj/jni/libyuv/source/rotate_neon64.cc +++ b/TMessagesProj/jni/libyuv/source/rotate_neon64.cc @@ -9,6 +9,7 @@ */ #include "libyuv/row.h" +#include "libyuv/rotate_row.h" #include "libyuv/basic_types.h" @@ -17,522 +18,524 @@ namespace libyuv { extern "C" { #endif +// This module is for GCC Neon armv8 64 bit. #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) -//this ifdef should be removed if TransposeWx8_NEON's aarch64 has -//been done -#ifdef HAS_TRANSPOSE_WX8_NEON + static uvec8 kVTbl4x4Transpose = - { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; + { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; void TransposeWx8_NEON(const uint8* src, int src_stride, - uint8* dst, int dst_stride, - int width) { + uint8* dst, int dst_stride, int width) { const uint8* src_temp = NULL; + int64 width64 = (int64) width; // Work around clang 3.4 warning. asm volatile ( // loops are on blocks of 8. loop will stop when // counter gets to or below 0. starting the counter // at w-8 allow for this - "sub %5, #8 \n" + "sub %3, %3, #8 \n" // handle 8x8 blocks. this should be the majority of the plane - ".p2align 2 \n" - "1: \n" - "mov %0, %1 \n" + "1: \n" + "mov %0, %1 \n" MEMACCESS(0) - "vld1.8 {d0}, [%0], %2 \n" + "ld1 {v0.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d1}, [%0], %2 \n" + "ld1 {v1.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d2}, [%0], %2 \n" + "ld1 {v2.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d3}, [%0], %2 \n" + "ld1 {v3.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d4}, [%0], %2 \n" + "ld1 {v4.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d5}, [%0], %2 \n" + "ld1 {v5.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d6}, [%0], %2 \n" + "ld1 {v6.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.8 {d7}, [%0] \n" + "ld1 {v7.8b}, [%0] \n" - "vtrn.8 d1, d0 \n" - "vtrn.8 d3, d2 \n" - "vtrn.8 d5, d4 \n" - "vtrn.8 d7, d6 \n" + "trn2 v16.8b, v0.8b, v1.8b \n" + "trn1 v17.8b, v0.8b, v1.8b \n" + "trn2 v18.8b, v2.8b, v3.8b \n" + "trn1 v19.8b, v2.8b, v3.8b \n" + "trn2 v20.8b, v4.8b, v5.8b \n" + "trn1 v21.8b, v4.8b, v5.8b \n" + "trn2 v22.8b, v6.8b, v7.8b \n" + "trn1 v23.8b, v6.8b, v7.8b \n" - "vtrn.16 d1, d3 \n" - "vtrn.16 d0, d2 \n" - "vtrn.16 d5, d7 \n" - "vtrn.16 d4, d6 \n" + "trn2 v3.4h, v17.4h, v19.4h \n" + "trn1 v1.4h, v17.4h, v19.4h \n" + "trn2 v2.4h, v16.4h, v18.4h \n" + "trn1 v0.4h, v16.4h, v18.4h \n" + "trn2 v7.4h, v21.4h, v23.4h \n" + "trn1 v5.4h, v21.4h, v23.4h \n" + "trn2 v6.4h, v20.4h, v22.4h \n" + "trn1 v4.4h, v20.4h, v22.4h \n" - "vtrn.32 d1, d5 \n" - "vtrn.32 d0, d4 \n" - "vtrn.32 d3, d7 \n" - "vtrn.32 d2, d6 \n" + "trn2 v21.2s, v1.2s, v5.2s \n" + "trn1 v17.2s, v1.2s, v5.2s \n" + "trn2 v20.2s, v0.2s, v4.2s \n" + "trn1 v16.2s, v0.2s, v4.2s \n" + "trn2 v23.2s, v3.2s, v7.2s \n" + "trn1 v19.2s, v3.2s, v7.2s \n" + "trn2 v22.2s, v2.2s, v6.2s \n" + "trn1 v18.2s, v2.2s, v6.2s \n" - "vrev16.8 q0, q0 \n" - "vrev16.8 q1, q1 \n" - "vrev16.8 q2, q2 \n" - "vrev16.8 q3, q3 \n" - - "mov %0, %3 \n" + "mov %0, %2 \n" MEMACCESS(0) - "vst1.8 {d1}, [%0], %4 \n" + "st1 {v17.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d0}, [%0], %4 \n" + "st1 {v16.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d3}, [%0], %4 \n" + "st1 {v19.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d2}, [%0], %4 \n" + "st1 {v18.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d5}, [%0], %4 \n" + "st1 {v21.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d4}, [%0], %4 \n" + "st1 {v20.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d7}, [%0], %4 \n" + "st1 {v23.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d6}, [%0] \n" + "st1 {v22.8b}, [%0] \n" - "add %1, #8 \n" // src += 8 - "add %3, %3, %4, lsl #3 \n" // dst += 8 * dst_stride - "subs %5, #8 \n" // w -= 8 - "bge 1b \n" + "add %1, %1, #8 \n" // src += 8 + "add %2, %2, %6, lsl #3 \n" // dst += 8 * dst_stride + "subs %3, %3, #8 \n" // w -= 8 + "b.ge 1b \n" // add 8 back to counter. if the result is 0 there are // no residuals. - "adds %5, #8 \n" - "beq 4f \n" + "adds %3, %3, #8 \n" + "b.eq 4f \n" // some residual, so between 1 and 7 lines left to transpose - "cmp %5, #2 \n" - "blt 3f \n" + "cmp %3, #2 \n" + "b.lt 3f \n" - "cmp %5, #4 \n" - "blt 2f \n" + "cmp %3, #4 \n" + "b.lt 2f \n" // 4x8 block - "mov %0, %1 \n" + "mov %0, %1 \n" MEMACCESS(0) - "vld1.32 {d0[0]}, [%0], %2 \n" + "ld1 {v0.s}[0], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d0[1]}, [%0], %2 \n" + "ld1 {v0.s}[1], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d1[0]}, [%0], %2 \n" + "ld1 {v0.s}[2], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d1[1]}, [%0], %2 \n" + "ld1 {v0.s}[3], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d2[0]}, [%0], %2 \n" + "ld1 {v1.s}[0], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d2[1]}, [%0], %2 \n" + "ld1 {v1.s}[1], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d3[0]}, [%0], %2 \n" + "ld1 {v1.s}[2], [%0], %5 \n" MEMACCESS(0) - "vld1.32 {d3[1]}, [%0] \n" + "ld1 {v1.s}[3], [%0] \n" - "mov %0, %3 \n" + "mov %0, %2 \n" - MEMACCESS(6) - "vld1.8 {q3}, [%6] \n" + MEMACCESS(4) + "ld1 {v2.16b}, [%4] \n" - "vtbl.8 d4, {d0, d1}, d6 \n" - "vtbl.8 d5, {d0, d1}, d7 \n" - "vtbl.8 d0, {d2, d3}, d6 \n" - "vtbl.8 d1, {d2, d3}, d7 \n" + "tbl v3.16b, {v0.16b}, v2.16b \n" + "tbl v0.16b, {v1.16b}, v2.16b \n" // TODO(frkoenig): Rework shuffle above to // write out with 4 instead of 8 writes. MEMACCESS(0) - "vst1.32 {d4[0]}, [%0], %4 \n" + "st1 {v3.s}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d4[1]}, [%0], %4 \n" + "st1 {v3.s}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d5[0]}, [%0], %4 \n" + "st1 {v3.s}[2], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d5[1]}, [%0] \n" + "st1 {v3.s}[3], [%0] \n" - "add %0, %3, #4 \n" + "add %0, %2, #4 \n" MEMACCESS(0) - "vst1.32 {d0[0]}, [%0], %4 \n" + "st1 {v0.s}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d0[1]}, [%0], %4 \n" + "st1 {v0.s}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d1[0]}, [%0], %4 \n" + "st1 {v0.s}[2], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d1[1]}, [%0] \n" + "st1 {v0.s}[3], [%0] \n" - "add %1, #4 \n" // src += 4 - "add %3, %3, %4, lsl #2 \n" // dst += 4 * dst_stride - "subs %5, #4 \n" // w -= 4 - "beq 4f \n" + "add %1, %1, #4 \n" // src += 4 + "add %2, %2, %6, lsl #2 \n" // dst += 4 * dst_stride + "subs %3, %3, #4 \n" // w -= 4 + "b.eq 4f \n" // some residual, check to see if it includes a 2x8 block, // or less - "cmp %5, #2 \n" - "blt 3f \n" + "cmp %3, #2 \n" + "b.lt 3f \n" // 2x8 block - "2: \n" - "mov %0, %1 \n" + "2: \n" + "mov %0, %1 \n" MEMACCESS(0) - "vld1.16 {d0[0]}, [%0], %2 \n" + "ld1 {v0.h}[0], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d1[0]}, [%0], %2 \n" + "ld1 {v1.h}[0], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d0[1]}, [%0], %2 \n" + "ld1 {v0.h}[1], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d1[1]}, [%0], %2 \n" + "ld1 {v1.h}[1], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d0[2]}, [%0], %2 \n" + "ld1 {v0.h}[2], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d1[2]}, [%0], %2 \n" + "ld1 {v1.h}[2], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d0[3]}, [%0], %2 \n" + "ld1 {v0.h}[3], [%0], %5 \n" MEMACCESS(0) - "vld1.16 {d1[3]}, [%0] \n" + "ld1 {v1.h}[3], [%0] \n" - "vtrn.8 d0, d1 \n" + "trn2 v2.8b, v0.8b, v1.8b \n" + "trn1 v3.8b, v0.8b, v1.8b \n" - "mov %0, %3 \n" + "mov %0, %2 \n" MEMACCESS(0) - "vst1.64 {d0}, [%0], %4 \n" + "st1 {v3.8b}, [%0], %6 \n" MEMACCESS(0) - "vst1.64 {d1}, [%0] \n" + "st1 {v2.8b}, [%0] \n" - "add %1, #2 \n" // src += 2 - "add %3, %3, %4, lsl #1 \n" // dst += 2 * dst_stride - "subs %5, #2 \n" // w -= 2 - "beq 4f \n" + "add %1, %1, #2 \n" // src += 2 + "add %2, %2, %6, lsl #1 \n" // dst += 2 * dst_stride + "subs %3, %3, #2 \n" // w -= 2 + "b.eq 4f \n" // 1x8 block - "3: \n" + "3: \n" MEMACCESS(1) - "vld1.8 {d0[0]}, [%1], %2 \n" + "ld1 {v0.b}[0], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[1]}, [%1], %2 \n" + "ld1 {v0.b}[1], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[2]}, [%1], %2 \n" + "ld1 {v0.b}[2], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[3]}, [%1], %2 \n" + "ld1 {v0.b}[3], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[4]}, [%1], %2 \n" + "ld1 {v0.b}[4], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[5]}, [%1], %2 \n" + "ld1 {v0.b}[5], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[6]}, [%1], %2 \n" + "ld1 {v0.b}[6], [%1], %5 \n" MEMACCESS(1) - "vld1.8 {d0[7]}, [%1] \n" + "ld1 {v0.b}[7], [%1] \n" - MEMACCESS(3) - "vst1.64 {d0}, [%3] \n" + MEMACCESS(2) + "st1 {v0.8b}, [%2] \n" - "4: \n" + "4: \n" - : "+r"(src_temp), // %0 - "+r"(src), // %1 - "+r"(src_stride), // %2 - "+r"(dst), // %3 - "+r"(dst_stride), // %4 - "+r"(width) // %5 - : "r"(&kVTbl4x4Transpose) // %6 - : "memory", "cc", "q0", "q1", "q2", "q3" + : "+r"(src_temp), // %0 + "+r"(src), // %1 + "+r"(dst), // %2 + "+r"(width64) // %3 + : "r"(&kVTbl4x4Transpose), // %4 + "r"(static_cast(src_stride)), // %5 + "r"(static_cast(dst_stride)) // %6 + : "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16", + "v17", "v18", "v19", "v20", "v21", "v22", "v23" ); } -#endif //HAS_TRANSPOSE_WX8_NEON -//this ifdef should be removed if TransposeUVWx8_NEON's aarch64 has -//been done -#ifdef HAS_TRANSPOSE_UVWX8_NEON -static uvec8 kVTbl4x4TransposeDi = - { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; +static uint8 kVTbl4x4TransposeDi[32] = + { 0, 16, 32, 48, 2, 18, 34, 50, 4, 20, 36, 52, 6, 22, 38, 54, + 1, 17, 33, 49, 3, 19, 35, 51, 5, 21, 37, 53, 7, 23, 39, 55}; void TransposeUVWx8_NEON(const uint8* src, int src_stride, uint8* dst_a, int dst_stride_a, uint8* dst_b, int dst_stride_b, int width) { const uint8* src_temp = NULL; + int64 width64 = (int64) width; // Work around clang 3.4 warning. asm volatile ( // loops are on blocks of 8. loop will stop when // counter gets to or below 0. starting the counter // at w-8 allow for this - "sub %7, #8 \n" + "sub %4, %4, #8 \n" // handle 8x8 blocks. this should be the majority of the plane - ".p2align 2 \n" "1: \n" - "mov %0, %1 \n" - - MEMACCESS(0) - "vld2.8 {d0, d1}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d2, d3}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d4, d5}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d6, d7}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d16, d17}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d18, d19}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d20, d21}, [%0], %2 \n" - MEMACCESS(0) - "vld2.8 {d22, d23}, [%0] \n" - - "vtrn.8 q1, q0 \n" - "vtrn.8 q3, q2 \n" - "vtrn.8 q9, q8 \n" - "vtrn.8 q11, q10 \n" - - "vtrn.16 q1, q3 \n" - "vtrn.16 q0, q2 \n" - "vtrn.16 q9, q11 \n" - "vtrn.16 q8, q10 \n" - - "vtrn.32 q1, q9 \n" - "vtrn.32 q0, q8 \n" - "vtrn.32 q3, q11 \n" - "vtrn.32 q2, q10 \n" - - "vrev16.8 q0, q0 \n" - "vrev16.8 q1, q1 \n" - "vrev16.8 q2, q2 \n" - "vrev16.8 q3, q3 \n" - "vrev16.8 q8, q8 \n" - "vrev16.8 q9, q9 \n" - "vrev16.8 q10, q10 \n" - "vrev16.8 q11, q11 \n" - - "mov %0, %3 \n" + "mov %0, %1 \n" MEMACCESS(0) - "vst1.8 {d2}, [%0], %4 \n" + "ld1 {v0.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d0}, [%0], %4 \n" + "ld1 {v1.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d6}, [%0], %4 \n" + "ld1 {v2.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d4}, [%0], %4 \n" + "ld1 {v3.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d18}, [%0], %4 \n" + "ld1 {v4.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d16}, [%0], %4 \n" + "ld1 {v5.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d22}, [%0], %4 \n" + "ld1 {v6.16b}, [%0], %5 \n" MEMACCESS(0) - "vst1.8 {d20}, [%0] \n" + "ld1 {v7.16b}, [%0] \n" - "mov %0, %5 \n" + "trn1 v16.16b, v0.16b, v1.16b \n" + "trn2 v17.16b, v0.16b, v1.16b \n" + "trn1 v18.16b, v2.16b, v3.16b \n" + "trn2 v19.16b, v2.16b, v3.16b \n" + "trn1 v20.16b, v4.16b, v5.16b \n" + "trn2 v21.16b, v4.16b, v5.16b \n" + "trn1 v22.16b, v6.16b, v7.16b \n" + "trn2 v23.16b, v6.16b, v7.16b \n" + + "trn1 v0.8h, v16.8h, v18.8h \n" + "trn2 v1.8h, v16.8h, v18.8h \n" + "trn1 v2.8h, v20.8h, v22.8h \n" + "trn2 v3.8h, v20.8h, v22.8h \n" + "trn1 v4.8h, v17.8h, v19.8h \n" + "trn2 v5.8h, v17.8h, v19.8h \n" + "trn1 v6.8h, v21.8h, v23.8h \n" + "trn2 v7.8h, v21.8h, v23.8h \n" + + "trn1 v16.4s, v0.4s, v2.4s \n" + "trn2 v17.4s, v0.4s, v2.4s \n" + "trn1 v18.4s, v1.4s, v3.4s \n" + "trn2 v19.4s, v1.4s, v3.4s \n" + "trn1 v20.4s, v4.4s, v6.4s \n" + "trn2 v21.4s, v4.4s, v6.4s \n" + "trn1 v22.4s, v5.4s, v7.4s \n" + "trn2 v23.4s, v5.4s, v7.4s \n" + + "mov %0, %2 \n" MEMACCESS(0) - "vst1.8 {d3}, [%0], %6 \n" + "st1 {v16.d}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d1}, [%0], %6 \n" + "st1 {v18.d}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d7}, [%0], %6 \n" + "st1 {v17.d}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d5}, [%0], %6 \n" + "st1 {v19.d}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d19}, [%0], %6 \n" + "st1 {v16.d}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d17}, [%0], %6 \n" + "st1 {v18.d}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d23}, [%0], %6 \n" + "st1 {v17.d}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.8 {d21}, [%0] \n" + "st1 {v19.d}[1], [%0] \n" - "add %1, #8*2 \n" // src += 8*2 - "add %3, %3, %4, lsl #3 \n" // dst_a += 8 * dst_stride_a - "add %5, %5, %6, lsl #3 \n" // dst_b += 8 * dst_stride_b - "subs %7, #8 \n" // w -= 8 - "bge 1b \n" + "mov %0, %3 \n" + + MEMACCESS(0) + "st1 {v20.d}[0], [%0], %7 \n" + MEMACCESS(0) + "st1 {v22.d}[0], [%0], %7 \n" + MEMACCESS(0) + "st1 {v21.d}[0], [%0], %7 \n" + MEMACCESS(0) + "st1 {v23.d}[0], [%0], %7 \n" + MEMACCESS(0) + "st1 {v20.d}[1], [%0], %7 \n" + MEMACCESS(0) + "st1 {v22.d}[1], [%0], %7 \n" + MEMACCESS(0) + "st1 {v21.d}[1], [%0], %7 \n" + MEMACCESS(0) + "st1 {v23.d}[1], [%0] \n" + + "add %1, %1, #16 \n" // src += 8*2 + "add %2, %2, %6, lsl #3 \n" // dst_a += 8 * dst_stride_a + "add %3, %3, %7, lsl #3 \n" // dst_b += 8 * dst_stride_b + "subs %4, %4, #8 \n" // w -= 8 + "b.ge 1b \n" // add 8 back to counter. if the result is 0 there are // no residuals. - "adds %7, #8 \n" - "beq 4f \n" + "adds %4, %4, #8 \n" + "b.eq 4f \n" // some residual, so between 1 and 7 lines left to transpose - "cmp %7, #2 \n" - "blt 3f \n" + "cmp %4, #2 \n" + "b.lt 3f \n" - "cmp %7, #4 \n" - "blt 2f \n" + "cmp %4, #4 \n" + "b.lt 2f \n" // TODO(frkoenig): Clean this up // 4x8 block - "mov %0, %1 \n" + "mov %0, %1 \n" MEMACCESS(0) - "vld1.64 {d0}, [%0], %2 \n" + "ld1 {v0.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d1}, [%0], %2 \n" + "ld1 {v1.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d2}, [%0], %2 \n" + "ld1 {v2.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d3}, [%0], %2 \n" + "ld1 {v3.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d4}, [%0], %2 \n" + "ld1 {v4.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d5}, [%0], %2 \n" + "ld1 {v5.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d6}, [%0], %2 \n" + "ld1 {v6.8b}, [%0], %5 \n" MEMACCESS(0) - "vld1.64 {d7}, [%0] \n" + "ld1 {v7.8b}, [%0] \n" MEMACCESS(8) - "vld1.8 {q15}, [%8] \n" + "ld1 {v30.16b}, [%8], #16 \n" + "ld1 {v31.16b}, [%8] \n" - "vtrn.8 q0, q1 \n" - "vtrn.8 q2, q3 \n" + "tbl v16.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v30.16b \n" + "tbl v17.16b, {v0.16b, v1.16b, v2.16b, v3.16b}, v31.16b \n" + "tbl v18.16b, {v4.16b, v5.16b, v6.16b, v7.16b}, v30.16b \n" + "tbl v19.16b, {v4.16b, v5.16b, v6.16b, v7.16b}, v31.16b \n" - "vtbl.8 d16, {d0, d1}, d30 \n" - "vtbl.8 d17, {d0, d1}, d31 \n" - "vtbl.8 d18, {d2, d3}, d30 \n" - "vtbl.8 d19, {d2, d3}, d31 \n" - "vtbl.8 d20, {d4, d5}, d30 \n" - "vtbl.8 d21, {d4, d5}, d31 \n" - "vtbl.8 d22, {d6, d7}, d30 \n" - "vtbl.8 d23, {d6, d7}, d31 \n" - - "mov %0, %3 \n" + "mov %0, %2 \n" MEMACCESS(0) - "vst1.32 {d16[0]}, [%0], %4 \n" + "st1 {v16.s}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d16[1]}, [%0], %4 \n" + "st1 {v16.s}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d17[0]}, [%0], %4 \n" + "st1 {v16.s}[2], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d17[1]}, [%0], %4 \n" + "st1 {v16.s}[3], [%0], %6 \n" - "add %0, %3, #4 \n" + "add %0, %2, #4 \n" MEMACCESS(0) - "vst1.32 {d20[0]}, [%0], %4 \n" + "st1 {v18.s}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d20[1]}, [%0], %4 \n" + "st1 {v18.s}[1], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d21[0]}, [%0], %4 \n" + "st1 {v18.s}[2], [%0], %6 \n" MEMACCESS(0) - "vst1.32 {d21[1]}, [%0] \n" + "st1 {v18.s}[3], [%0] \n" - "mov %0, %5 \n" + "mov %0, %3 \n" MEMACCESS(0) - "vst1.32 {d18[0]}, [%0], %6 \n" + "st1 {v17.s}[0], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d18[1]}, [%0], %6 \n" + "st1 {v17.s}[1], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d19[0]}, [%0], %6 \n" + "st1 {v17.s}[2], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d19[1]}, [%0], %6 \n" + "st1 {v17.s}[3], [%0], %7 \n" - "add %0, %5, #4 \n" + "add %0, %3, #4 \n" MEMACCESS(0) - "vst1.32 {d22[0]}, [%0], %6 \n" + "st1 {v19.s}[0], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d22[1]}, [%0], %6 \n" + "st1 {v19.s}[1], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d23[0]}, [%0], %6 \n" + "st1 {v19.s}[2], [%0], %7 \n" MEMACCESS(0) - "vst1.32 {d23[1]}, [%0] \n" + "st1 {v19.s}[3], [%0] \n" - "add %1, #4*2 \n" // src += 4 * 2 - "add %3, %3, %4, lsl #2 \n" // dst_a += 4 * dst_stride_a - "add %5, %5, %6, lsl #2 \n" // dst_b += 4 * dst_stride_b - "subs %7, #4 \n" // w -= 4 - "beq 4f \n" + "add %1, %1, #8 \n" // src += 4 * 2 + "add %2, %2, %6, lsl #2 \n" // dst_a += 4 * dst_stride_a + "add %3, %3, %7, lsl #2 \n" // dst_b += 4 * dst_stride_b + "subs %4, %4, #4 \n" // w -= 4 + "b.eq 4f \n" // some residual, check to see if it includes a 2x8 block, // or less - "cmp %7, #2 \n" - "blt 3f \n" + "cmp %4, #2 \n" + "b.lt 3f \n" // 2x8 block "2: \n" - "mov %0, %1 \n" + "mov %0, %1 \n" MEMACCESS(0) - "vld2.16 {d0[0], d2[0]}, [%0], %2 \n" + "ld2 {v0.h, v1.h}[0], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d1[0], d3[0]}, [%0], %2 \n" + "ld2 {v2.h, v3.h}[0], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d0[1], d2[1]}, [%0], %2 \n" + "ld2 {v0.h, v1.h}[1], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d1[1], d3[1]}, [%0], %2 \n" + "ld2 {v2.h, v3.h}[1], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d0[2], d2[2]}, [%0], %2 \n" + "ld2 {v0.h, v1.h}[2], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d1[2], d3[2]}, [%0], %2 \n" + "ld2 {v2.h, v3.h}[2], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d0[3], d2[3]}, [%0], %2 \n" + "ld2 {v0.h, v1.h}[3], [%0], %5 \n" MEMACCESS(0) - "vld2.16 {d1[3], d3[3]}, [%0] \n" + "ld2 {v2.h, v3.h}[3], [%0] \n" - "vtrn.8 d0, d1 \n" - "vtrn.8 d2, d3 \n" + "trn1 v4.8b, v0.8b, v2.8b \n" + "trn2 v5.8b, v0.8b, v2.8b \n" + "trn1 v6.8b, v1.8b, v3.8b \n" + "trn2 v7.8b, v1.8b, v3.8b \n" - "mov %0, %3 \n" + "mov %0, %2 \n" MEMACCESS(0) - "vst1.64 {d0}, [%0], %4 \n" + "st1 {v4.d}[0], [%0], %6 \n" MEMACCESS(0) - "vst1.64 {d2}, [%0] \n" + "st1 {v6.d}[0], [%0] \n" - "mov %0, %5 \n" + "mov %0, %3 \n" MEMACCESS(0) - "vst1.64 {d1}, [%0], %6 \n" + "st1 {v5.d}[0], [%0], %7 \n" MEMACCESS(0) - "vst1.64 {d3}, [%0] \n" + "st1 {v7.d}[0], [%0] \n" - "add %1, #2*2 \n" // src += 2 * 2 - "add %3, %3, %4, lsl #1 \n" // dst_a += 2 * dst_stride_a - "add %5, %5, %6, lsl #1 \n" // dst_b += 2 * dst_stride_b - "subs %7, #2 \n" // w -= 2 - "beq 4f \n" + "add %1, %1, #4 \n" // src += 2 * 2 + "add %2, %2, %6, lsl #1 \n" // dst_a += 2 * dst_stride_a + "add %3, %3, %7, lsl #1 \n" // dst_b += 2 * dst_stride_b + "subs %4, %4, #2 \n" // w -= 2 + "b.eq 4f \n" // 1x8 block "3: \n" MEMACCESS(1) - "vld2.8 {d0[0], d1[0]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[0], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[1], d1[1]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[1], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[2], d1[2]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[2], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[3], d1[3]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[3], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[4], d1[4]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[4], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[5], d1[5]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[5], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[6], d1[6]}, [%1], %2 \n" + "ld2 {v0.b, v1.b}[6], [%1], %5 \n" MEMACCESS(1) - "vld2.8 {d0[7], d1[7]}, [%1] \n" + "ld2 {v0.b, v1.b}[7], [%1] \n" + MEMACCESS(2) + "st1 {v0.d}[0], [%2] \n" MEMACCESS(3) - "vst1.64 {d0}, [%3] \n" - MEMACCESS(5) - "vst1.64 {d1}, [%5] \n" + "st1 {v1.d}[0], [%3] \n" "4: \n" - : "+r"(src_temp), // %0 - "+r"(src), // %1 - "+r"(src_stride), // %2 - "+r"(dst_a), // %3 - "+r"(dst_stride_a), // %4 - "+r"(dst_b), // %5 - "+r"(dst_stride_b), // %6 - "+r"(width) // %7 - : "r"(&kVTbl4x4TransposeDi) // %8 + : "+r"(src_temp), // %0 + "+r"(src), // %1 + "+r"(dst_a), // %2 + "+r"(dst_b), // %3 + "+r"(width64) // %4 + : "r"(static_cast(src_stride)), // %5 + "r"(static_cast(dst_stride_a)), // %6 + "r"(static_cast(dst_stride_b)), // %7 + "r"(&kVTbl4x4TransposeDi) // %8 : "memory", "cc", - "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11" + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v30", "v31" ); } -#endif // HAS_TRANSPOSE_UVWX8_NEON -#endif // __aarch64__ +#endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/row_any.cc b/TMessagesProj/jni/libyuv/source/row_any.cc index aaa0378d..5e5f435a 100644 --- a/TMessagesProj/jni/libyuv/source/row_any.cc +++ b/TMessagesProj/jni/libyuv/source/row_any.cc @@ -10,6 +10,8 @@ #include "libyuv/row.h" +#include // For memset. + #include "libyuv/basic_types.h" #ifdef __cplusplus @@ -17,584 +19,799 @@ namespace libyuv { extern "C" { #endif -// TODO(fbarchard): Consider 'any' functions handling any quantity of pixels. -// TODO(fbarchard): Consider 'any' functions handling odd alignment. -// YUV to RGB does multiple of 8 with SIMD and remainder with C. -#define YANY(NAMEANY, I420TORGB_SIMD, I420TORGB_C, UV_SHIFT, BPP, MASK) \ - void NAMEANY(const uint8* y_buf, \ - const uint8* u_buf, \ - const uint8* v_buf, \ - uint8* rgb_buf, \ - int width) { \ +// Subsampled source needs to be increase by 1 of not even. +#define SS(width, shift) (((width) + (1 << (shift)) - 1) >> (shift)) + +// Any 4 planes to 1 with yuvconstants +#define ANY41C(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \ + void NAMEANY(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, \ + const uint8* a_buf, uint8* dst_ptr, \ + const struct YuvConstants* yuvconstants, int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 5]); \ + memset(temp, 0, 64 * 4); /* for msan */ \ + int r = width & MASK; \ int n = width & ~MASK; \ - I420TORGB_SIMD(y_buf, u_buf, v_buf, rgb_buf, n); \ - I420TORGB_C(y_buf + n, \ - u_buf + (n >> UV_SHIFT), \ - v_buf + (n >> UV_SHIFT), \ - rgb_buf + n * BPP, width & MASK); \ + if (n > 0) { \ + ANY_SIMD(y_buf, u_buf, v_buf, a_buf, dst_ptr, yuvconstants, n); \ + } \ + memcpy(temp, y_buf + n, r); \ + memcpy(temp + 64, u_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + memcpy(temp + 128, v_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + memcpy(temp + 192, a_buf + n, r); \ + ANY_SIMD(temp, temp + 64, temp + 128, temp + 192, temp + 256, \ + yuvconstants, MASK + 1); \ + memcpy(dst_ptr + (n >> DUVSHIFT) * BPP, temp + 256, \ + SS(r, DUVSHIFT) * BPP); \ + } + +#ifdef HAS_I422ALPHATOARGBROW_SSSE3 +ANY41C(I422AlphaToARGBRow_Any_SSSE3, I422AlphaToARGBRow_SSSE3, 1, 0, 4, 7) +#endif +#ifdef HAS_I422ALPHATOARGBROW_AVX2 +ANY41C(I422AlphaToARGBRow_Any_AVX2, I422AlphaToARGBRow_AVX2, 1, 0, 4, 15) +#endif +#ifdef HAS_I422ALPHATOARGBROW_NEON +ANY41C(I422AlphaToARGBRow_Any_NEON, I422AlphaToARGBRow_NEON, 1, 0, 4, 7) +#endif +#undef ANY41C + +// Any 3 planes to 1. +#define ANY31(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \ + void NAMEANY(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, \ + uint8* dst_ptr, int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 4]); \ + memset(temp, 0, 64 * 3); /* for YUY2 and msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(y_buf, u_buf, v_buf, dst_ptr, n); \ + } \ + memcpy(temp, y_buf + n, r); \ + memcpy(temp + 64, u_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + memcpy(temp + 128, v_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + ANY_SIMD(temp, temp + 64, temp + 128, temp + 192, MASK + 1); \ + memcpy(dst_ptr + (n >> DUVSHIFT) * BPP, temp + 192, \ + SS(r, DUVSHIFT) * BPP); \ + } +#ifdef HAS_I422TOYUY2ROW_SSE2 +ANY31(I422ToYUY2Row_Any_SSE2, I422ToYUY2Row_SSE2, 1, 1, 4, 15) +ANY31(I422ToUYVYRow_Any_SSE2, I422ToUYVYRow_SSE2, 1, 1, 4, 15) +#endif +#ifdef HAS_I422TOYUY2ROW_NEON +ANY31(I422ToYUY2Row_Any_NEON, I422ToYUY2Row_NEON, 1, 1, 4, 15) +#endif +#ifdef HAS_I422TOUYVYROW_NEON +ANY31(I422ToUYVYRow_Any_NEON, I422ToUYVYRow_NEON, 1, 1, 4, 15) +#endif +#ifdef HAS_BLENDPLANEROW_AVX2 +ANY31(BlendPlaneRow_Any_AVX2, BlendPlaneRow_AVX2, 0, 0, 1, 31) +#endif +#ifdef HAS_BLENDPLANEROW_SSSE3 +ANY31(BlendPlaneRow_Any_SSSE3, BlendPlaneRow_SSSE3, 0, 0, 1, 7) +#endif +#undef ANY31 + +// Note that odd width replication includes 444 due to implementation +// on arm that subsamples 444 to 422 internally. +// Any 3 planes to 1 with yuvconstants +#define ANY31C(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, BPP, MASK) \ + void NAMEANY(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, \ + uint8* dst_ptr, const struct YuvConstants* yuvconstants, \ + int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 4]); \ + memset(temp, 0, 64 * 3); /* for YUY2 and msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(y_buf, u_buf, v_buf, dst_ptr, yuvconstants, n); \ + } \ + memcpy(temp, y_buf + n, r); \ + memcpy(temp + 64, u_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + memcpy(temp + 128, v_buf + (n >> UVSHIFT), SS(r, UVSHIFT)); \ + if (width & 1) { \ + temp[64 + SS(r, UVSHIFT)] = temp[64 + SS(r, UVSHIFT) - 1]; \ + temp[128 + SS(r, UVSHIFT)] = temp[128 + SS(r, UVSHIFT) - 1]; \ + } \ + ANY_SIMD(temp, temp + 64, temp + 128, temp + 192, \ + yuvconstants, MASK + 1); \ + memcpy(dst_ptr + (n >> DUVSHIFT) * BPP, temp + 192, \ + SS(r, DUVSHIFT) * BPP); \ } #ifdef HAS_I422TOARGBROW_SSSE3 -YANY(I422ToARGBRow_Any_SSSE3, I422ToARGBRow_Unaligned_SSSE3, I422ToARGBRow_C, - 1, 4, 7) -#endif // HAS_I422TOARGBROW_SSSE3 +ANY31C(I422ToARGBRow_Any_SSSE3, I422ToARGBRow_SSSE3, 1, 0, 4, 7) +#endif +#ifdef HAS_I411TOARGBROW_SSSE3 +ANY31C(I411ToARGBRow_Any_SSSE3, I411ToARGBRow_SSSE3, 2, 0, 4, 7) +#endif #ifdef HAS_I444TOARGBROW_SSSE3 -YANY(I444ToARGBRow_Any_SSSE3, I444ToARGBRow_Unaligned_SSSE3, I444ToARGBRow_C, - 0, 4, 7) -YANY(I411ToARGBRow_Any_SSSE3, I411ToARGBRow_Unaligned_SSSE3, I411ToARGBRow_C, - 2, 4, 7) -YANY(I422ToBGRARow_Any_SSSE3, I422ToBGRARow_Unaligned_SSSE3, I422ToBGRARow_C, - 1, 4, 7) -YANY(I422ToABGRRow_Any_SSSE3, I422ToABGRRow_Unaligned_SSSE3, I422ToABGRRow_C, - 1, 4, 7) -YANY(I422ToRGBARow_Any_SSSE3, I422ToRGBARow_Unaligned_SSSE3, I422ToRGBARow_C, - 1, 4, 7) -// I422ToRGB565Row_SSSE3 is unaligned. -YANY(I422ToARGB4444Row_Any_SSSE3, I422ToARGB4444Row_SSSE3, I422ToARGB4444Row_C, - 1, 2, 7) -YANY(I422ToARGB1555Row_Any_SSSE3, I422ToARGB1555Row_SSSE3, I422ToARGB1555Row_C, - 1, 2, 7) -YANY(I422ToRGB565Row_Any_SSSE3, I422ToRGB565Row_SSSE3, I422ToRGB565Row_C, - 1, 2, 7) -// I422ToRGB24Row_SSSE3 is unaligned. -YANY(I422ToRGB24Row_Any_SSSE3, I422ToRGB24Row_SSSE3, I422ToRGB24Row_C, 1, 3, 7) -YANY(I422ToRAWRow_Any_SSSE3, I422ToRAWRow_SSSE3, I422ToRAWRow_C, 1, 3, 7) -YANY(I422ToYUY2Row_Any_SSE2, I422ToYUY2Row_SSE2, I422ToYUY2Row_C, 1, 2, 15) -YANY(I422ToUYVYRow_Any_SSE2, I422ToUYVYRow_SSE2, I422ToUYVYRow_C, 1, 2, 15) +ANY31C(I444ToARGBRow_Any_SSSE3, I444ToARGBRow_SSSE3, 0, 0, 4, 7) +ANY31C(I422ToRGBARow_Any_SSSE3, I422ToRGBARow_SSSE3, 1, 0, 4, 7) +ANY31C(I422ToARGB4444Row_Any_SSSE3, I422ToARGB4444Row_SSSE3, 1, 0, 2, 7) +ANY31C(I422ToARGB1555Row_Any_SSSE3, I422ToARGB1555Row_SSSE3, 1, 0, 2, 7) +ANY31C(I422ToRGB565Row_Any_SSSE3, I422ToRGB565Row_SSSE3, 1, 0, 2, 7) +ANY31C(I422ToRGB24Row_Any_SSSE3, I422ToRGB24Row_SSSE3, 1, 0, 3, 7) #endif // HAS_I444TOARGBROW_SSSE3 +#ifdef HAS_I422TORGB24ROW_AVX2 +ANY31C(I422ToRGB24Row_Any_AVX2, I422ToRGB24Row_AVX2, 1, 0, 3, 15) +#endif #ifdef HAS_I422TOARGBROW_AVX2 -YANY(I422ToARGBRow_Any_AVX2, I422ToARGBRow_AVX2, I422ToARGBRow_C, 1, 4, 15) -#endif // HAS_I422TOARGBROW_AVX2 +ANY31C(I422ToARGBRow_Any_AVX2, I422ToARGBRow_AVX2, 1, 0, 4, 15) +#endif +#ifdef HAS_I422TORGBAROW_AVX2 +ANY31C(I422ToRGBARow_Any_AVX2, I422ToRGBARow_AVX2, 1, 0, 4, 15) +#endif +#ifdef HAS_I444TOARGBROW_AVX2 +ANY31C(I444ToARGBRow_Any_AVX2, I444ToARGBRow_AVX2, 0, 0, 4, 15) +#endif +#ifdef HAS_I411TOARGBROW_AVX2 +ANY31C(I411ToARGBRow_Any_AVX2, I411ToARGBRow_AVX2, 2, 0, 4, 15) +#endif +#ifdef HAS_I422TOARGB4444ROW_AVX2 +ANY31C(I422ToARGB4444Row_Any_AVX2, I422ToARGB4444Row_AVX2, 1, 0, 2, 7) +#endif +#ifdef HAS_I422TOARGB1555ROW_AVX2 +ANY31C(I422ToARGB1555Row_Any_AVX2, I422ToARGB1555Row_AVX2, 1, 0, 2, 7) +#endif +#ifdef HAS_I422TORGB565ROW_AVX2 +ANY31C(I422ToRGB565Row_Any_AVX2, I422ToRGB565Row_AVX2, 1, 0, 2, 7) +#endif #ifdef HAS_I422TOARGBROW_NEON -YANY(I444ToARGBRow_Any_NEON, I444ToARGBRow_NEON, I444ToARGBRow_C, 0, 4, 7) -YANY(I422ToARGBRow_Any_NEON, I422ToARGBRow_NEON, I422ToARGBRow_C, 1, 4, 7) -YANY(I411ToARGBRow_Any_NEON, I411ToARGBRow_NEON, I411ToARGBRow_C, 2, 4, 7) -YANY(I422ToBGRARow_Any_NEON, I422ToBGRARow_NEON, I422ToBGRARow_C, 1, 4, 7) -YANY(I422ToABGRRow_Any_NEON, I422ToABGRRow_NEON, I422ToABGRRow_C, 1, 4, 7) -YANY(I422ToRGBARow_Any_NEON, I422ToRGBARow_NEON, I422ToRGBARow_C, 1, 4, 7) -YANY(I422ToRGB24Row_Any_NEON, I422ToRGB24Row_NEON, I422ToRGB24Row_C, 1, 3, 7) -YANY(I422ToRAWRow_Any_NEON, I422ToRAWRow_NEON, I422ToRAWRow_C, 1, 3, 7) -YANY(I422ToARGB4444Row_Any_NEON, I422ToARGB4444Row_NEON, I422ToARGB4444Row_C, - 1, 2, 7) -YANY(I422ToARGB1555Row_Any_NEON, I422ToARGB1555Row_NEON, I422ToARGB1555Row_C, - 1, 2, 7) -YANY(I422ToRGB565Row_Any_NEON, I422ToRGB565Row_NEON, I422ToRGB565Row_C, 1, 2, 7) -#endif // HAS_I422TOARGBROW_NEON -#ifdef HAS_I422TOYUY2ROW_NEON -YANY(I422ToYUY2Row_Any_NEON, I422ToYUY2Row_NEON, I422ToYUY2Row_C, 1, 2, 15) -#endif // HAS_I422TOYUY2ROW_NEON -#ifdef HAS_I422TOUYVYROW_NEON -YANY(I422ToUYVYRow_Any_NEON, I422ToUYVYRow_NEON, I422ToUYVYRow_C, 1, 2, 15) -#endif // HAS_I422TOUYVYROW_NEON -#undef YANY +ANY31C(I444ToARGBRow_Any_NEON, I444ToARGBRow_NEON, 0, 0, 4, 7) +ANY31C(I422ToARGBRow_Any_NEON, I422ToARGBRow_NEON, 1, 0, 4, 7) +ANY31C(I411ToARGBRow_Any_NEON, I411ToARGBRow_NEON, 2, 0, 4, 7) +ANY31C(I422ToRGBARow_Any_NEON, I422ToRGBARow_NEON, 1, 0, 4, 7) +ANY31C(I422ToRGB24Row_Any_NEON, I422ToRGB24Row_NEON, 1, 0, 3, 7) +ANY31C(I422ToARGB4444Row_Any_NEON, I422ToARGB4444Row_NEON, 1, 0, 2, 7) +ANY31C(I422ToARGB1555Row_Any_NEON, I422ToARGB1555Row_NEON, 1, 0, 2, 7) +ANY31C(I422ToRGB565Row_Any_NEON, I422ToRGB565Row_NEON, 1, 0, 2, 7) +#endif +#undef ANY31C -// Wrappers to handle odd width -#define NV2NY(NAMEANY, NV12TORGB_SIMD, NV12TORGB_C, UV_SHIFT, BPP) \ - void NAMEANY(const uint8* y_buf, \ - const uint8* uv_buf, \ - uint8* rgb_buf, \ - int width) { \ - int n = width & ~7; \ - NV12TORGB_SIMD(y_buf, uv_buf, rgb_buf, n); \ - NV12TORGB_C(y_buf + n, \ - uv_buf + (n >> UV_SHIFT), \ - rgb_buf + n * BPP, width & 7); \ - } - -#ifdef HAS_NV12TOARGBROW_SSSE3 -NV2NY(NV12ToARGBRow_Any_SSSE3, NV12ToARGBRow_Unaligned_SSSE3, NV12ToARGBRow_C, - 0, 4) -NV2NY(NV21ToARGBRow_Any_SSSE3, NV21ToARGBRow_Unaligned_SSSE3, NV21ToARGBRow_C, - 0, 4) -#endif // HAS_NV12TOARGBROW_SSSE3 -#ifdef HAS_NV12TOARGBROW_NEON -NV2NY(NV12ToARGBRow_Any_NEON, NV12ToARGBRow_NEON, NV12ToARGBRow_C, 0, 4) -NV2NY(NV21ToARGBRow_Any_NEON, NV21ToARGBRow_NEON, NV21ToARGBRow_C, 0, 4) -#endif // HAS_NV12TOARGBROW_NEON -#ifdef HAS_NV12TORGB565ROW_SSSE3 -NV2NY(NV12ToRGB565Row_Any_SSSE3, NV12ToRGB565Row_SSSE3, NV12ToRGB565Row_C, - 0, 2) -NV2NY(NV21ToRGB565Row_Any_SSSE3, NV21ToRGB565Row_SSSE3, NV21ToRGB565Row_C, - 0, 2) -#endif // HAS_NV12TORGB565ROW_SSSE3 -#ifdef HAS_NV12TORGB565ROW_NEON -NV2NY(NV12ToRGB565Row_Any_NEON, NV12ToRGB565Row_NEON, NV12ToRGB565Row_C, 0, 2) -NV2NY(NV21ToRGB565Row_Any_NEON, NV21ToRGB565Row_NEON, NV21ToRGB565Row_C, 0, 2) -#endif // HAS_NV12TORGB565ROW_NEON -#undef NVANY - -#define RGBANY(NAMEANY, ARGBTORGB_SIMD, ARGBTORGB_C, MASK, SBPP, BPP) \ - void NAMEANY(const uint8* src, \ - uint8* dst, \ - int width) { \ +// Any 2 planes to 1. +#define ANY21(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, SBPP2, BPP, MASK) \ + void NAMEANY(const uint8* y_buf, const uint8* uv_buf, \ + uint8* dst_ptr, int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 3]); \ + memset(temp, 0, 64 * 2); /* for msan */ \ + int r = width & MASK; \ int n = width & ~MASK; \ - ARGBTORGB_SIMD(src, dst, n); \ - ARGBTORGB_C(src + n * SBPP, dst + n * BPP, width & MASK); \ - } - -#if defined(HAS_ARGBTORGB24ROW_SSSE3) -RGBANY(ARGBToRGB24Row_Any_SSSE3, ARGBToRGB24Row_SSSE3, ARGBToRGB24Row_C, - 15, 4, 3) -RGBANY(ARGBToRAWRow_Any_SSSE3, ARGBToRAWRow_SSSE3, ARGBToRAWRow_C, - 15, 4, 3) -RGBANY(ARGBToRGB565Row_Any_SSE2, ARGBToRGB565Row_SSE2, ARGBToRGB565Row_C, - 3, 4, 2) -RGBANY(ARGBToARGB1555Row_Any_SSE2, ARGBToARGB1555Row_SSE2, ARGBToARGB1555Row_C, - 3, 4, 2) -RGBANY(ARGBToARGB4444Row_Any_SSE2, ARGBToARGB4444Row_SSE2, ARGBToARGB4444Row_C, - 3, 4, 2) -#endif -#if defined(HAS_I400TOARGBROW_SSE2) -RGBANY(I400ToARGBRow_Any_SSE2, I400ToARGBRow_Unaligned_SSE2, I400ToARGBRow_C, - 7, 1, 4) -#endif -#if defined(HAS_YTOARGBROW_SSE2) -RGBANY(YToARGBRow_Any_SSE2, YToARGBRow_SSE2, YToARGBRow_C, - 7, 1, 4) -RGBANY(YUY2ToARGBRow_Any_SSSE3, YUY2ToARGBRow_Unaligned_SSSE3, YUY2ToARGBRow_C, - 15, 2, 4) -RGBANY(UYVYToARGBRow_Any_SSSE3, UYVYToARGBRow_Unaligned_SSSE3, UYVYToARGBRow_C, - 15, 2, 4) -// These require alignment on ARGB, so C is used for remainder. -RGBANY(RGB24ToARGBRow_Any_SSSE3, RGB24ToARGBRow_SSSE3, RGB24ToARGBRow_C, - 15, 3, 4) -RGBANY(RAWToARGBRow_Any_SSSE3, RAWToARGBRow_SSSE3, RAWToARGBRow_C, - 15, 3, 4) -RGBANY(RGB565ToARGBRow_Any_SSE2, RGB565ToARGBRow_SSE2, RGB565ToARGBRow_C, - 7, 2, 4) -RGBANY(ARGB1555ToARGBRow_Any_SSE2, ARGB1555ToARGBRow_SSE2, ARGB1555ToARGBRow_C, - 7, 2, 4) -RGBANY(ARGB4444ToARGBRow_Any_SSE2, ARGB4444ToARGBRow_SSE2, ARGB4444ToARGBRow_C, - 7, 2, 4) -#endif -#if defined(HAS_ARGBTORGB24ROW_NEON) -RGBANY(ARGBToRGB24Row_Any_NEON, ARGBToRGB24Row_NEON, ARGBToRGB24Row_C, 7, 4, 3) -RGBANY(ARGBToRAWRow_Any_NEON, ARGBToRAWRow_NEON, ARGBToRAWRow_C, 7, 4, 3) -RGBANY(ARGBToRGB565Row_Any_NEON, ARGBToRGB565Row_NEON, ARGBToRGB565Row_C, - 7, 4, 2) -RGBANY(ARGBToARGB1555Row_Any_NEON, ARGBToARGB1555Row_NEON, ARGBToARGB1555Row_C, - 7, 4, 2) -RGBANY(ARGBToARGB4444Row_Any_NEON, ARGBToARGB4444Row_NEON, ARGBToARGB4444Row_C, - 7, 4, 2) -RGBANY(I400ToARGBRow_Any_NEON, I400ToARGBRow_NEON, I400ToARGBRow_C, - 7, 1, 4) -RGBANY(YToARGBRow_Any_NEON, YToARGBRow_NEON, YToARGBRow_C, - 7, 1, 4) -RGBANY(YUY2ToARGBRow_Any_NEON, YUY2ToARGBRow_NEON, YUY2ToARGBRow_C, - 7, 2, 4) -RGBANY(UYVYToARGBRow_Any_NEON, UYVYToARGBRow_NEON, UYVYToARGBRow_C, - 7, 2, 4) -#endif -#undef RGBANY - -// ARGB to Bayer does multiple of 4 pixels, SSSE3 aligned src, unaligned dst. -#define BAYERANY(NAMEANY, ARGBTORGB_SIMD, ARGBTORGB_C, MASK, SBPP, BPP) \ - void NAMEANY(const uint8* src, \ - uint8* dst, uint32 selector, \ - int width) { \ - int n = width & ~MASK; \ - ARGBTORGB_SIMD(src, dst, selector, n); \ - ARGBTORGB_C(src + n * SBPP, dst + n * BPP, selector, width & MASK); \ - } - -#if defined(HAS_ARGBTOBAYERROW_SSSE3) -BAYERANY(ARGBToBayerRow_Any_SSSE3, ARGBToBayerRow_SSSE3, ARGBToBayerRow_C, - 7, 4, 1) -#endif -#if defined(HAS_ARGBTOBAYERROW_NEON) -BAYERANY(ARGBToBayerRow_Any_NEON, ARGBToBayerRow_NEON, ARGBToBayerRow_C, - 7, 4, 1) -#endif -#if defined(HAS_ARGBTOBAYERGGROW_SSE2) -BAYERANY(ARGBToBayerGGRow_Any_SSE2, ARGBToBayerGGRow_SSE2, ARGBToBayerGGRow_C, - 7, 4, 1) -#endif -#if defined(HAS_ARGBTOBAYERGGROW_NEON) -BAYERANY(ARGBToBayerGGRow_Any_NEON, ARGBToBayerGGRow_NEON, ARGBToBayerGGRow_C, - 7, 4, 1) -#endif - -#undef BAYERANY - -// RGB/YUV to Y does multiple of 16 with SIMD and last 16 with SIMD. -#define YANY(NAMEANY, ARGBTOY_SIMD, SBPP, BPP, NUM) \ - void NAMEANY(const uint8* src_argb, uint8* dst_y, int width) { \ - ARGBTOY_SIMD(src_argb, dst_y, width - NUM); \ - ARGBTOY_SIMD(src_argb + (width - NUM) * SBPP, \ - dst_y + (width - NUM) * BPP, NUM); \ - } - -#ifdef HAS_ARGBTOYROW_AVX2 -YANY(ARGBToYRow_Any_AVX2, ARGBToYRow_AVX2, 4, 1, 32) -YANY(ARGBToYJRow_Any_AVX2, ARGBToYJRow_AVX2, 4, 1, 32) -YANY(YUY2ToYRow_Any_AVX2, YUY2ToYRow_AVX2, 2, 1, 32) -YANY(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 2, 1, 32) -#endif -#ifdef HAS_ARGBTOYROW_SSSE3 -YANY(ARGBToYRow_Any_SSSE3, ARGBToYRow_Unaligned_SSSE3, 4, 1, 16) -#endif -#ifdef HAS_BGRATOYROW_SSSE3 -YANY(BGRAToYRow_Any_SSSE3, BGRAToYRow_Unaligned_SSSE3, 4, 1, 16) -YANY(ABGRToYRow_Any_SSSE3, ABGRToYRow_Unaligned_SSSE3, 4, 1, 16) -YANY(RGBAToYRow_Any_SSSE3, RGBAToYRow_Unaligned_SSSE3, 4, 1, 16) -YANY(YUY2ToYRow_Any_SSE2, YUY2ToYRow_Unaligned_SSE2, 2, 1, 16) -YANY(UYVYToYRow_Any_SSE2, UYVYToYRow_Unaligned_SSE2, 2, 1, 16) -#endif -#ifdef HAS_ARGBTOYJROW_SSSE3 -YANY(ARGBToYJRow_Any_SSSE3, ARGBToYJRow_Unaligned_SSSE3, 4, 1, 16) -#endif -#ifdef HAS_ARGBTOYROW_NEON -YANY(ARGBToYRow_Any_NEON, ARGBToYRow_NEON, 4, 1, 8) -#endif -#ifdef HAS_ARGBTOYJROW_NEON -YANY(ARGBToYJRow_Any_NEON, ARGBToYJRow_NEON, 4, 1, 8) -#endif -#ifdef HAS_BGRATOYROW_NEON -YANY(BGRAToYRow_Any_NEON, BGRAToYRow_NEON, 4, 1, 8) -#endif -#ifdef HAS_ABGRTOYROW_NEON -YANY(ABGRToYRow_Any_NEON, ABGRToYRow_NEON, 4, 1, 8) -#endif -#ifdef HAS_RGBATOYROW_NEON -YANY(RGBAToYRow_Any_NEON, RGBAToYRow_NEON, 4, 1, 8) -#endif -#ifdef HAS_RGB24TOYROW_NEON -YANY(RGB24ToYRow_Any_NEON, RGB24ToYRow_NEON, 3, 1, 8) -#endif -#ifdef HAS_RAWTOYROW_NEON -YANY(RAWToYRow_Any_NEON, RAWToYRow_NEON, 3, 1, 8) -#endif -#ifdef HAS_RGB565TOYROW_NEON -YANY(RGB565ToYRow_Any_NEON, RGB565ToYRow_NEON, 2, 1, 8) -#endif -#ifdef HAS_ARGB1555TOYROW_NEON -YANY(ARGB1555ToYRow_Any_NEON, ARGB1555ToYRow_NEON, 2, 1, 8) -#endif -#ifdef HAS_ARGB4444TOYROW_NEON -YANY(ARGB4444ToYRow_Any_NEON, ARGB4444ToYRow_NEON, 2, 1, 8) -#endif -#ifdef HAS_YUY2TOYROW_NEON -YANY(YUY2ToYRow_Any_NEON, YUY2ToYRow_NEON, 2, 1, 16) -#endif -#ifdef HAS_UYVYTOYROW_NEON -YANY(UYVYToYRow_Any_NEON, UYVYToYRow_NEON, 2, 1, 16) -#endif -#ifdef HAS_RGB24TOARGBROW_NEON -YANY(RGB24ToARGBRow_Any_NEON, RGB24ToARGBRow_NEON, 3, 4, 8) -#endif -#ifdef HAS_RAWTOARGBROW_NEON -YANY(RAWToARGBRow_Any_NEON, RAWToARGBRow_NEON, 3, 4, 8) -#endif -#ifdef HAS_RGB565TOARGBROW_NEON -YANY(RGB565ToARGBRow_Any_NEON, RGB565ToARGBRow_NEON, 2, 4, 8) -#endif -#ifdef HAS_ARGB1555TOARGBROW_NEON -YANY(ARGB1555ToARGBRow_Any_NEON, ARGB1555ToARGBRow_NEON, 2, 4, 8) -#endif -#ifdef HAS_ARGB4444TOARGBROW_NEON -YANY(ARGB4444ToARGBRow_Any_NEON, ARGB4444ToARGBRow_NEON, 2, 4, 8) -#endif -#undef YANY - -#define YANY(NAMEANY, ARGBTOY_SIMD, ARGBTOY_C, SBPP, BPP, MASK) \ - void NAMEANY(const uint8* src_argb, uint8* dst_y, int width) { \ - int n = width & ~MASK; \ - ARGBTOY_SIMD(src_argb, dst_y, n); \ - ARGBTOY_C(src_argb + n * SBPP, \ - dst_y + n * BPP, width & MASK); \ - } - -// Attenuate is destructive so last16 method can not be used due to overlap. -#ifdef HAS_ARGBATTENUATEROW_SSSE3 -YANY(ARGBAttenuateRow_Any_SSSE3, ARGBAttenuateRow_SSSE3, ARGBAttenuateRow_C, - 4, 4, 3) -#endif -#ifdef HAS_ARGBATTENUATEROW_SSE2 -YANY(ARGBAttenuateRow_Any_SSE2, ARGBAttenuateRow_SSE2, ARGBAttenuateRow_C, - 4, 4, 3) -#endif -#ifdef HAS_ARGBUNATTENUATEROW_SSE2 -YANY(ARGBUnattenuateRow_Any_SSE2, ARGBUnattenuateRow_SSE2, ARGBUnattenuateRow_C, - 4, 4, 3) -#endif -#ifdef HAS_ARGBATTENUATEROW_AVX2 -YANY(ARGBAttenuateRow_Any_AVX2, ARGBAttenuateRow_AVX2, ARGBAttenuateRow_C, - 4, 4, 7) -#endif -#ifdef HAS_ARGBUNATTENUATEROW_AVX2 -YANY(ARGBUnattenuateRow_Any_AVX2, ARGBUnattenuateRow_AVX2, ARGBUnattenuateRow_C, - 4, 4, 7) -#endif -#ifdef HAS_ARGBATTENUATEROW_NEON -YANY(ARGBAttenuateRow_Any_NEON, ARGBAttenuateRow_NEON, ARGBAttenuateRow_C, - 4, 4, 7) -#endif -#undef YANY - -// RGB/YUV to UV does multiple of 16 with SIMD and remainder with C. -#define UVANY(NAMEANY, ANYTOUV_SIMD, ANYTOUV_C, BPP, MASK) \ - void NAMEANY(const uint8* src_argb, int src_stride_argb, \ - uint8* dst_u, uint8* dst_v, int width) { \ - int n = width & ~MASK; \ - ANYTOUV_SIMD(src_argb, src_stride_argb, dst_u, dst_v, n); \ - ANYTOUV_C(src_argb + n * BPP, src_stride_argb, \ - dst_u + (n >> 1), \ - dst_v + (n >> 1), \ - width & MASK); \ - } - -#ifdef HAS_ARGBTOUVROW_AVX2 -UVANY(ARGBToUVRow_Any_AVX2, ARGBToUVRow_AVX2, ARGBToUVRow_C, 4, 31) -UVANY(YUY2ToUVRow_Any_AVX2, YUY2ToUVRow_AVX2, YUY2ToUVRow_C, 2, 31) -UVANY(UYVYToUVRow_Any_AVX2, UYVYToUVRow_AVX2, UYVYToUVRow_C, 2, 31) -#endif -#ifdef HAS_ARGBTOUVROW_SSSE3 -UVANY(ARGBToUVRow_Any_SSSE3, ARGBToUVRow_Unaligned_SSSE3, ARGBToUVRow_C, 4, 15) -UVANY(ARGBToUVJRow_Any_SSSE3, ARGBToUVJRow_Unaligned_SSSE3, ARGBToUVJRow_C, - 4, 15) -UVANY(BGRAToUVRow_Any_SSSE3, BGRAToUVRow_Unaligned_SSSE3, BGRAToUVRow_C, 4, 15) -UVANY(ABGRToUVRow_Any_SSSE3, ABGRToUVRow_Unaligned_SSSE3, ABGRToUVRow_C, 4, 15) -UVANY(RGBAToUVRow_Any_SSSE3, RGBAToUVRow_Unaligned_SSSE3, RGBAToUVRow_C, 4, 15) -UVANY(YUY2ToUVRow_Any_SSE2, YUY2ToUVRow_Unaligned_SSE2, YUY2ToUVRow_C, 2, 15) -UVANY(UYVYToUVRow_Any_SSE2, UYVYToUVRow_Unaligned_SSE2, UYVYToUVRow_C, 2, 15) -#endif -#ifdef HAS_ARGBTOUVROW_NEON -UVANY(ARGBToUVRow_Any_NEON, ARGBToUVRow_NEON, ARGBToUVRow_C, 4, 15) -#endif -#ifdef HAS_ARGBTOUVJROW_NEON -UVANY(ARGBToUVJRow_Any_NEON, ARGBToUVJRow_NEON, ARGBToUVJRow_C, 4, 15) -#endif -#ifdef HAS_BGRATOUVROW_NEON -UVANY(BGRAToUVRow_Any_NEON, BGRAToUVRow_NEON, BGRAToUVRow_C, 4, 15) -#endif -#ifdef HAS_ABGRTOUVROW_NEON -UVANY(ABGRToUVRow_Any_NEON, ABGRToUVRow_NEON, ABGRToUVRow_C, 4, 15) -#endif -#ifdef HAS_RGBATOUVROW_NEON -UVANY(RGBAToUVRow_Any_NEON, RGBAToUVRow_NEON, RGBAToUVRow_C, 4, 15) -#endif -#ifdef HAS_RGB24TOUVROW_NEON -UVANY(RGB24ToUVRow_Any_NEON, RGB24ToUVRow_NEON, RGB24ToUVRow_C, 3, 15) -#endif -#ifdef HAS_RAWTOUVROW_NEON -UVANY(RAWToUVRow_Any_NEON, RAWToUVRow_NEON, RAWToUVRow_C, 3, 15) -#endif -#ifdef HAS_RGB565TOUVROW_NEON -UVANY(RGB565ToUVRow_Any_NEON, RGB565ToUVRow_NEON, RGB565ToUVRow_C, 2, 15) -#endif -#ifdef HAS_ARGB1555TOUVROW_NEON -UVANY(ARGB1555ToUVRow_Any_NEON, ARGB1555ToUVRow_NEON, ARGB1555ToUVRow_C, 2, 15) -#endif -#ifdef HAS_ARGB4444TOUVROW_NEON -UVANY(ARGB4444ToUVRow_Any_NEON, ARGB4444ToUVRow_NEON, ARGB4444ToUVRow_C, 2, 15) -#endif -#ifdef HAS_YUY2TOUVROW_NEON -UVANY(YUY2ToUVRow_Any_NEON, YUY2ToUVRow_NEON, YUY2ToUVRow_C, 2, 15) -#endif -#ifdef HAS_UYVYTOUVROW_NEON -UVANY(UYVYToUVRow_Any_NEON, UYVYToUVRow_NEON, UYVYToUVRow_C, 2, 15) -#endif -#undef UVANY - -#define UV422ANY(NAMEANY, ANYTOUV_SIMD, ANYTOUV_C, BPP, MASK, SHIFT) \ - void NAMEANY(const uint8* src_uv, \ - uint8* dst_u, uint8* dst_v, int width) { \ - int n = width & ~MASK; \ - ANYTOUV_SIMD(src_uv, dst_u, dst_v, n); \ - ANYTOUV_C(src_uv + n * BPP, \ - dst_u + (n >> SHIFT), \ - dst_v + (n >> SHIFT), \ - width & MASK); \ - } - -#ifdef HAS_ARGBTOUV444ROW_SSSE3 -UV422ANY(ARGBToUV444Row_Any_SSSE3, ARGBToUV444Row_Unaligned_SSSE3, - ARGBToUV444Row_C, 4, 15, 0) -#endif -#ifdef HAS_YUY2TOUV422ROW_AVX2 -UV422ANY(YUY2ToUV422Row_Any_AVX2, YUY2ToUV422Row_AVX2, - YUY2ToUV422Row_C, 2, 31, 1) -UV422ANY(UYVYToUV422Row_Any_AVX2, UYVYToUV422Row_AVX2, - UYVYToUV422Row_C, 2, 31, 1) -#endif -#ifdef HAS_ARGBTOUVROW_SSSE3 -UV422ANY(ARGBToUV422Row_Any_SSSE3, ARGBToUV422Row_Unaligned_SSSE3, - ARGBToUV422Row_C, 4, 15, 1) -UV422ANY(YUY2ToUV422Row_Any_SSE2, YUY2ToUV422Row_Unaligned_SSE2, - YUY2ToUV422Row_C, 2, 15, 1) -UV422ANY(UYVYToUV422Row_Any_SSE2, UYVYToUV422Row_Unaligned_SSE2, - UYVYToUV422Row_C, 2, 15, 1) -#endif -#ifdef HAS_YUY2TOUV422ROW_NEON -UV422ANY(ARGBToUV444Row_Any_NEON, ARGBToUV444Row_NEON, - ARGBToUV444Row_C, 4, 7, 0) -UV422ANY(ARGBToUV422Row_Any_NEON, ARGBToUV422Row_NEON, - ARGBToUV422Row_C, 4, 15, 1) -UV422ANY(ARGBToUV411Row_Any_NEON, ARGBToUV411Row_NEON, - ARGBToUV411Row_C, 4, 31, 2) -UV422ANY(YUY2ToUV422Row_Any_NEON, YUY2ToUV422Row_NEON, - YUY2ToUV422Row_C, 2, 15, 1) -UV422ANY(UYVYToUV422Row_Any_NEON, UYVYToUV422Row_NEON, - UYVYToUV422Row_C, 2, 15, 1) -#endif -#undef UV422ANY - -#define SPLITUVROWANY(NAMEANY, ANYTOUV_SIMD, ANYTOUV_C, MASK) \ - void NAMEANY(const uint8* src_uv, \ - uint8* dst_u, uint8* dst_v, int width) { \ - int n = width & ~MASK; \ - ANYTOUV_SIMD(src_uv, dst_u, dst_v, n); \ - ANYTOUV_C(src_uv + n * 2, \ - dst_u + n, \ - dst_v + n, \ - width & MASK); \ - } - -#ifdef HAS_SPLITUVROW_SSE2 -SPLITUVROWANY(SplitUVRow_Any_SSE2, SplitUVRow_Unaligned_SSE2, SplitUVRow_C, 15) -#endif -#ifdef HAS_SPLITUVROW_AVX2 -SPLITUVROWANY(SplitUVRow_Any_AVX2, SplitUVRow_AVX2, SplitUVRow_C, 31) -#endif -#ifdef HAS_SPLITUVROW_NEON -SPLITUVROWANY(SplitUVRow_Any_NEON, SplitUVRow_NEON, SplitUVRow_C, 15) -#endif -#ifdef HAS_SPLITUVROW_MIPS_DSPR2 -SPLITUVROWANY(SplitUVRow_Any_MIPS_DSPR2, SplitUVRow_Unaligned_MIPS_DSPR2, - SplitUVRow_C, 15) -#endif -#undef SPLITUVROWANY - -#define MERGEUVROW_ANY(NAMEANY, ANYTOUV_SIMD, ANYTOUV_C, MASK) \ - void NAMEANY(const uint8* src_u, const uint8* src_v, \ - uint8* dst_uv, int width) { \ - int n = width & ~MASK; \ - ANYTOUV_SIMD(src_u, src_v, dst_uv, n); \ - ANYTOUV_C(src_u + n, \ - src_v + n, \ - dst_uv + n * 2, \ - width & MASK); \ + if (n > 0) { \ + ANY_SIMD(y_buf, uv_buf, dst_ptr, n); \ + } \ + memcpy(temp, y_buf + n * SBPP, r * SBPP); \ + memcpy(temp + 64, uv_buf + (n >> UVSHIFT) * SBPP2, \ + SS(r, UVSHIFT) * SBPP2); \ + ANY_SIMD(temp, temp + 64, temp + 128, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ } +// Merge functions. #ifdef HAS_MERGEUVROW_SSE2 -MERGEUVROW_ANY(MergeUVRow_Any_SSE2, MergeUVRow_Unaligned_SSE2, MergeUVRow_C, 15) +ANY21(MergeUVRow_Any_SSE2, MergeUVRow_SSE2, 0, 1, 1, 2, 15) #endif #ifdef HAS_MERGEUVROW_AVX2 -MERGEUVROW_ANY(MergeUVRow_Any_AVX2, MergeUVRow_AVX2, MergeUVRow_C, 31) +ANY21(MergeUVRow_Any_AVX2, MergeUVRow_AVX2, 0, 1, 1, 2, 31) #endif #ifdef HAS_MERGEUVROW_NEON -MERGEUVROW_ANY(MergeUVRow_Any_NEON, MergeUVRow_NEON, MergeUVRow_C, 15) +ANY21(MergeUVRow_Any_NEON, MergeUVRow_NEON, 0, 1, 1, 2, 15) #endif -#undef MERGEUVROW_ANY - -#define MATHROW_ANY(NAMEANY, ARGBMATH_SIMD, ARGBMATH_C, MASK) \ - void NAMEANY(const uint8* src_argb0, const uint8* src_argb1, \ - uint8* dst_argb, int width) { \ - int n = width & ~MASK; \ - ARGBMATH_SIMD(src_argb0, src_argb1, dst_argb, n); \ - ARGBMATH_C(src_argb0 + n * 4, \ - src_argb1 + n * 4, \ - dst_argb + n * 4, \ - width & MASK); \ - } +// Math functions. #ifdef HAS_ARGBMULTIPLYROW_SSE2 -MATHROW_ANY(ARGBMultiplyRow_Any_SSE2, ARGBMultiplyRow_SSE2, ARGBMultiplyRow_C, - 3) +ANY21(ARGBMultiplyRow_Any_SSE2, ARGBMultiplyRow_SSE2, 0, 4, 4, 4, 3) #endif #ifdef HAS_ARGBADDROW_SSE2 -MATHROW_ANY(ARGBAddRow_Any_SSE2, ARGBAddRow_SSE2, ARGBAddRow_C, 3) +ANY21(ARGBAddRow_Any_SSE2, ARGBAddRow_SSE2, 0, 4, 4, 4, 3) #endif #ifdef HAS_ARGBSUBTRACTROW_SSE2 -MATHROW_ANY(ARGBSubtractRow_Any_SSE2, ARGBSubtractRow_SSE2, ARGBSubtractRow_C, - 3) +ANY21(ARGBSubtractRow_Any_SSE2, ARGBSubtractRow_SSE2, 0, 4, 4, 4, 3) #endif #ifdef HAS_ARGBMULTIPLYROW_AVX2 -MATHROW_ANY(ARGBMultiplyRow_Any_AVX2, ARGBMultiplyRow_AVX2, ARGBMultiplyRow_C, - 7) +ANY21(ARGBMultiplyRow_Any_AVX2, ARGBMultiplyRow_AVX2, 0, 4, 4, 4, 7) #endif #ifdef HAS_ARGBADDROW_AVX2 -MATHROW_ANY(ARGBAddRow_Any_AVX2, ARGBAddRow_AVX2, ARGBAddRow_C, 7) +ANY21(ARGBAddRow_Any_AVX2, ARGBAddRow_AVX2, 0, 4, 4, 4, 7) #endif #ifdef HAS_ARGBSUBTRACTROW_AVX2 -MATHROW_ANY(ARGBSubtractRow_Any_AVX2, ARGBSubtractRow_AVX2, ARGBSubtractRow_C, - 7) +ANY21(ARGBSubtractRow_Any_AVX2, ARGBSubtractRow_AVX2, 0, 4, 4, 4, 7) #endif #ifdef HAS_ARGBMULTIPLYROW_NEON -MATHROW_ANY(ARGBMultiplyRow_Any_NEON, ARGBMultiplyRow_NEON, ARGBMultiplyRow_C, - 7) +ANY21(ARGBMultiplyRow_Any_NEON, ARGBMultiplyRow_NEON, 0, 4, 4, 4, 7) #endif #ifdef HAS_ARGBADDROW_NEON -MATHROW_ANY(ARGBAddRow_Any_NEON, ARGBAddRow_NEON, ARGBAddRow_C, 7) +ANY21(ARGBAddRow_Any_NEON, ARGBAddRow_NEON, 0, 4, 4, 4, 7) #endif #ifdef HAS_ARGBSUBTRACTROW_NEON -MATHROW_ANY(ARGBSubtractRow_Any_NEON, ARGBSubtractRow_NEON, ARGBSubtractRow_C, - 7) +ANY21(ARGBSubtractRow_Any_NEON, ARGBSubtractRow_NEON, 0, 4, 4, 4, 7) #endif -#undef MATHROW_ANY +#ifdef HAS_SOBELROW_SSE2 +ANY21(SobelRow_Any_SSE2, SobelRow_SSE2, 0, 1, 1, 4, 15) +#endif +#ifdef HAS_SOBELROW_NEON +ANY21(SobelRow_Any_NEON, SobelRow_NEON, 0, 1, 1, 4, 7) +#endif +#ifdef HAS_SOBELTOPLANEROW_SSE2 +ANY21(SobelToPlaneRow_Any_SSE2, SobelToPlaneRow_SSE2, 0, 1, 1, 1, 15) +#endif +#ifdef HAS_SOBELTOPLANEROW_NEON +ANY21(SobelToPlaneRow_Any_NEON, SobelToPlaneRow_NEON, 0, 1, 1, 1, 15) +#endif +#ifdef HAS_SOBELXYROW_SSE2 +ANY21(SobelXYRow_Any_SSE2, SobelXYRow_SSE2, 0, 1, 1, 4, 15) +#endif +#ifdef HAS_SOBELXYROW_NEON +ANY21(SobelXYRow_Any_NEON, SobelXYRow_NEON, 0, 1, 1, 4, 7) +#endif +#undef ANY21 -// Shuffle may want to work in place, so last16 method can not be used. -#define YANY(NAMEANY, ARGBTOY_SIMD, ARGBTOY_C, SBPP, BPP, MASK) \ - void NAMEANY(const uint8* src_argb, uint8* dst_argb, \ - const uint8* shuffler, int width) { \ +// Any 2 planes to 1 with yuvconstants +#define ANY21C(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, SBPP2, BPP, MASK) \ + void NAMEANY(const uint8* y_buf, const uint8* uv_buf, \ + uint8* dst_ptr, const struct YuvConstants* yuvconstants, \ + int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 3]); \ + memset(temp, 0, 64 * 2); /* for msan */ \ + int r = width & MASK; \ int n = width & ~MASK; \ - ARGBTOY_SIMD(src_argb, dst_argb, shuffler, n); \ - ARGBTOY_C(src_argb + n * SBPP, \ - dst_argb + n * BPP, shuffler, width & MASK); \ + if (n > 0) { \ + ANY_SIMD(y_buf, uv_buf, dst_ptr, yuvconstants, n); \ + } \ + memcpy(temp, y_buf + n * SBPP, r * SBPP); \ + memcpy(temp + 64, uv_buf + (n >> UVSHIFT) * SBPP2, \ + SS(r, UVSHIFT) * SBPP2); \ + ANY_SIMD(temp, temp + 64, temp + 128, yuvconstants, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ } +// Biplanar to RGB. +#ifdef HAS_NV12TOARGBROW_SSSE3 +ANY21C(NV12ToARGBRow_Any_SSSE3, NV12ToARGBRow_SSSE3, 1, 1, 2, 4, 7) +#endif +#ifdef HAS_NV12TOARGBROW_AVX2 +ANY21C(NV12ToARGBRow_Any_AVX2, NV12ToARGBRow_AVX2, 1, 1, 2, 4, 15) +#endif +#ifdef HAS_NV12TOARGBROW_NEON +ANY21C(NV12ToARGBRow_Any_NEON, NV12ToARGBRow_NEON, 1, 1, 2, 4, 7) +#endif +#ifdef HAS_NV21TOARGBROW_SSSE3 +ANY21C(NV21ToARGBRow_Any_SSSE3, NV21ToARGBRow_SSSE3, 1, 1, 2, 4, 7) +#endif +#ifdef HAS_NV21TOARGBROW_AVX2 +ANY21C(NV21ToARGBRow_Any_AVX2, NV21ToARGBRow_AVX2, 1, 1, 2, 4, 15) +#endif +#ifdef HAS_NV21TOARGBROW_NEON +ANY21C(NV21ToARGBRow_Any_NEON, NV21ToARGBRow_NEON, 1, 1, 2, 4, 7) +#endif +#ifdef HAS_NV12TORGB565ROW_SSSE3 +ANY21C(NV12ToRGB565Row_Any_SSSE3, NV12ToRGB565Row_SSSE3, 1, 1, 2, 2, 7) +#endif +#ifdef HAS_NV12TORGB565ROW_AVX2 +ANY21C(NV12ToRGB565Row_Any_AVX2, NV12ToRGB565Row_AVX2, 1, 1, 2, 2, 15) +#endif +#ifdef HAS_NV12TORGB565ROW_NEON +ANY21C(NV12ToRGB565Row_Any_NEON, NV12ToRGB565Row_NEON, 1, 1, 2, 2, 7) +#endif +#undef ANY21C + +// Any 1 to 1. +#define ANY11(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_ptr, int width) { \ + SIMD_ALIGNED(uint8 temp[128 * 2]); \ + memset(temp, 0, 128); /* for YUY2 and msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_ptr, n); \ + } \ + memcpy(temp, src_ptr + (n >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \ + ANY_SIMD(temp, temp + 128, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ + } + +#ifdef HAS_COPYROW_AVX +ANY11(CopyRow_Any_AVX, CopyRow_AVX, 0, 1, 1, 63) +#endif +#ifdef HAS_COPYROW_SSE2 +ANY11(CopyRow_Any_SSE2, CopyRow_SSE2, 0, 1, 1, 31) +#endif +#ifdef HAS_COPYROW_NEON +ANY11(CopyRow_Any_NEON, CopyRow_NEON, 0, 1, 1, 31) +#endif +#if defined(HAS_ARGBTORGB24ROW_SSSE3) +ANY11(ARGBToRGB24Row_Any_SSSE3, ARGBToRGB24Row_SSSE3, 0, 4, 3, 15) +ANY11(ARGBToRAWRow_Any_SSSE3, ARGBToRAWRow_SSSE3, 0, 4, 3, 15) +ANY11(ARGBToRGB565Row_Any_SSE2, ARGBToRGB565Row_SSE2, 0, 4, 2, 3) +ANY11(ARGBToARGB1555Row_Any_SSE2, ARGBToARGB1555Row_SSE2, 0, 4, 2, 3) +ANY11(ARGBToARGB4444Row_Any_SSE2, ARGBToARGB4444Row_SSE2, 0, 4, 2, 3) +#endif +#if defined(HAS_ARGBTORGB565ROW_AVX2) +ANY11(ARGBToRGB565Row_Any_AVX2, ARGBToRGB565Row_AVX2, 0, 4, 2, 7) +#endif +#if defined(HAS_ARGBTOARGB4444ROW_AVX2) +ANY11(ARGBToARGB1555Row_Any_AVX2, ARGBToARGB1555Row_AVX2, 0, 4, 2, 7) +ANY11(ARGBToARGB4444Row_Any_AVX2, ARGBToARGB4444Row_AVX2, 0, 4, 2, 7) +#endif +#if defined(HAS_J400TOARGBROW_SSE2) +ANY11(J400ToARGBRow_Any_SSE2, J400ToARGBRow_SSE2, 0, 1, 4, 7) +#endif +#if defined(HAS_J400TOARGBROW_AVX2) +ANY11(J400ToARGBRow_Any_AVX2, J400ToARGBRow_AVX2, 0, 1, 4, 15) +#endif +#if defined(HAS_I400TOARGBROW_SSE2) +ANY11(I400ToARGBRow_Any_SSE2, I400ToARGBRow_SSE2, 0, 1, 4, 7) +#endif +#if defined(HAS_I400TOARGBROW_AVX2) +ANY11(I400ToARGBRow_Any_AVX2, I400ToARGBRow_AVX2, 0, 1, 4, 15) +#endif +#if defined(HAS_RGB24TOARGBROW_SSSE3) +ANY11(RGB24ToARGBRow_Any_SSSE3, RGB24ToARGBRow_SSSE3, 0, 3, 4, 15) +ANY11(RAWToARGBRow_Any_SSSE3, RAWToARGBRow_SSSE3, 0, 3, 4, 15) +ANY11(RGB565ToARGBRow_Any_SSE2, RGB565ToARGBRow_SSE2, 0, 2, 4, 7) +ANY11(ARGB1555ToARGBRow_Any_SSE2, ARGB1555ToARGBRow_SSE2, 0, 2, 4, 7) +ANY11(ARGB4444ToARGBRow_Any_SSE2, ARGB4444ToARGBRow_SSE2, 0, 2, 4, 7) +#endif +#if defined(HAS_RAWTORGB24ROW_SSSE3) +ANY11(RAWToRGB24Row_Any_SSSE3, RAWToRGB24Row_SSSE3, 0, 3, 3, 7) +#endif +#if defined(HAS_RGB565TOARGBROW_AVX2) +ANY11(RGB565ToARGBRow_Any_AVX2, RGB565ToARGBRow_AVX2, 0, 2, 4, 15) +#endif +#if defined(HAS_ARGB1555TOARGBROW_AVX2) +ANY11(ARGB1555ToARGBRow_Any_AVX2, ARGB1555ToARGBRow_AVX2, 0, 2, 4, 15) +#endif +#if defined(HAS_ARGB4444TOARGBROW_AVX2) +ANY11(ARGB4444ToARGBRow_Any_AVX2, ARGB4444ToARGBRow_AVX2, 0, 2, 4, 15) +#endif +#if defined(HAS_ARGBTORGB24ROW_NEON) +ANY11(ARGBToRGB24Row_Any_NEON, ARGBToRGB24Row_NEON, 0, 4, 3, 7) +ANY11(ARGBToRAWRow_Any_NEON, ARGBToRAWRow_NEON, 0, 4, 3, 7) +ANY11(ARGBToRGB565Row_Any_NEON, ARGBToRGB565Row_NEON, 0, 4, 2, 7) +ANY11(ARGBToARGB1555Row_Any_NEON, ARGBToARGB1555Row_NEON, 0, 4, 2, 7) +ANY11(ARGBToARGB4444Row_Any_NEON, ARGBToARGB4444Row_NEON, 0, 4, 2, 7) +ANY11(J400ToARGBRow_Any_NEON, J400ToARGBRow_NEON, 0, 1, 4, 7) +ANY11(I400ToARGBRow_Any_NEON, I400ToARGBRow_NEON, 0, 1, 4, 7) +#endif +#if defined(HAS_RAWTORGB24ROW_NEON) +ANY11(RAWToRGB24Row_Any_NEON, RAWToRGB24Row_NEON, 0, 3, 3, 7) +#endif +#ifdef HAS_ARGBTOYROW_AVX2 +ANY11(ARGBToYRow_Any_AVX2, ARGBToYRow_AVX2, 0, 4, 1, 31) +#endif +#ifdef HAS_ARGBTOYJROW_AVX2 +ANY11(ARGBToYJRow_Any_AVX2, ARGBToYJRow_AVX2, 0, 4, 1, 31) +#endif +#ifdef HAS_UYVYTOYROW_AVX2 +ANY11(UYVYToYRow_Any_AVX2, UYVYToYRow_AVX2, 0, 2, 1, 31) +#endif +#ifdef HAS_YUY2TOYROW_AVX2 +ANY11(YUY2ToYRow_Any_AVX2, YUY2ToYRow_AVX2, 1, 4, 1, 31) +#endif +#ifdef HAS_ARGBTOYROW_SSSE3 +ANY11(ARGBToYRow_Any_SSSE3, ARGBToYRow_SSSE3, 0, 4, 1, 15) +#endif +#ifdef HAS_BGRATOYROW_SSSE3 +ANY11(BGRAToYRow_Any_SSSE3, BGRAToYRow_SSSE3, 0, 4, 1, 15) +ANY11(ABGRToYRow_Any_SSSE3, ABGRToYRow_SSSE3, 0, 4, 1, 15) +ANY11(RGBAToYRow_Any_SSSE3, RGBAToYRow_SSSE3, 0, 4, 1, 15) +ANY11(YUY2ToYRow_Any_SSE2, YUY2ToYRow_SSE2, 1, 4, 1, 15) +ANY11(UYVYToYRow_Any_SSE2, UYVYToYRow_SSE2, 1, 4, 1, 15) +#endif +#ifdef HAS_ARGBTOYJROW_SSSE3 +ANY11(ARGBToYJRow_Any_SSSE3, ARGBToYJRow_SSSE3, 0, 4, 1, 15) +#endif +#ifdef HAS_ARGBTOYROW_NEON +ANY11(ARGBToYRow_Any_NEON, ARGBToYRow_NEON, 0, 4, 1, 7) +#endif +#ifdef HAS_ARGBTOYJROW_NEON +ANY11(ARGBToYJRow_Any_NEON, ARGBToYJRow_NEON, 0, 4, 1, 7) +#endif +#ifdef HAS_BGRATOYROW_NEON +ANY11(BGRAToYRow_Any_NEON, BGRAToYRow_NEON, 0, 4, 1, 7) +#endif +#ifdef HAS_ABGRTOYROW_NEON +ANY11(ABGRToYRow_Any_NEON, ABGRToYRow_NEON, 0, 4, 1, 7) +#endif +#ifdef HAS_RGBATOYROW_NEON +ANY11(RGBAToYRow_Any_NEON, RGBAToYRow_NEON, 0, 4, 1, 7) +#endif +#ifdef HAS_RGB24TOYROW_NEON +ANY11(RGB24ToYRow_Any_NEON, RGB24ToYRow_NEON, 0, 3, 1, 7) +#endif +#ifdef HAS_RAWTOYROW_NEON +ANY11(RAWToYRow_Any_NEON, RAWToYRow_NEON, 0, 3, 1, 7) +#endif +#ifdef HAS_RGB565TOYROW_NEON +ANY11(RGB565ToYRow_Any_NEON, RGB565ToYRow_NEON, 0, 2, 1, 7) +#endif +#ifdef HAS_ARGB1555TOYROW_NEON +ANY11(ARGB1555ToYRow_Any_NEON, ARGB1555ToYRow_NEON, 0, 2, 1, 7) +#endif +#ifdef HAS_ARGB4444TOYROW_NEON +ANY11(ARGB4444ToYRow_Any_NEON, ARGB4444ToYRow_NEON, 0, 2, 1, 7) +#endif +#ifdef HAS_YUY2TOYROW_NEON +ANY11(YUY2ToYRow_Any_NEON, YUY2ToYRow_NEON, 1, 4, 1, 15) +#endif +#ifdef HAS_UYVYTOYROW_NEON +ANY11(UYVYToYRow_Any_NEON, UYVYToYRow_NEON, 0, 2, 1, 15) +#endif +#ifdef HAS_RGB24TOARGBROW_NEON +ANY11(RGB24ToARGBRow_Any_NEON, RGB24ToARGBRow_NEON, 0, 3, 4, 7) +#endif +#ifdef HAS_RAWTOARGBROW_NEON +ANY11(RAWToARGBRow_Any_NEON, RAWToARGBRow_NEON, 0, 3, 4, 7) +#endif +#ifdef HAS_RGB565TOARGBROW_NEON +ANY11(RGB565ToARGBRow_Any_NEON, RGB565ToARGBRow_NEON, 0, 2, 4, 7) +#endif +#ifdef HAS_ARGB1555TOARGBROW_NEON +ANY11(ARGB1555ToARGBRow_Any_NEON, ARGB1555ToARGBRow_NEON, 0, 2, 4, 7) +#endif +#ifdef HAS_ARGB4444TOARGBROW_NEON +ANY11(ARGB4444ToARGBRow_Any_NEON, ARGB4444ToARGBRow_NEON, 0, 2, 4, 7) +#endif +#ifdef HAS_ARGBATTENUATEROW_SSSE3 +ANY11(ARGBAttenuateRow_Any_SSSE3, ARGBAttenuateRow_SSSE3, 0, 4, 4, 3) +#endif +#ifdef HAS_ARGBUNATTENUATEROW_SSE2 +ANY11(ARGBUnattenuateRow_Any_SSE2, ARGBUnattenuateRow_SSE2, 0, 4, 4, 3) +#endif +#ifdef HAS_ARGBATTENUATEROW_AVX2 +ANY11(ARGBAttenuateRow_Any_AVX2, ARGBAttenuateRow_AVX2, 0, 4, 4, 7) +#endif +#ifdef HAS_ARGBUNATTENUATEROW_AVX2 +ANY11(ARGBUnattenuateRow_Any_AVX2, ARGBUnattenuateRow_AVX2, 0, 4, 4, 7) +#endif +#ifdef HAS_ARGBATTENUATEROW_NEON +ANY11(ARGBAttenuateRow_Any_NEON, ARGBAttenuateRow_NEON, 0, 4, 4, 7) +#endif +#undef ANY11 + +// Any 1 to 1 with yuvconstants +#define ANY11C(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_ptr, \ + const struct YuvConstants* yuvconstants, int width) { \ + SIMD_ALIGNED(uint8 temp[128 * 2]); \ + memset(temp, 0, 128); /* for YUY2 and msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_ptr, yuvconstants, n); \ + } \ + memcpy(temp, src_ptr + (n >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \ + ANY_SIMD(temp, temp + 128, yuvconstants, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ + } +#if defined(HAS_YUY2TOARGBROW_SSSE3) +ANY11C(YUY2ToARGBRow_Any_SSSE3, YUY2ToARGBRow_SSSE3, 1, 4, 4, 15) +ANY11C(UYVYToARGBRow_Any_SSSE3, UYVYToARGBRow_SSSE3, 1, 4, 4, 15) +#endif +#if defined(HAS_YUY2TOARGBROW_AVX2) +ANY11C(YUY2ToARGBRow_Any_AVX2, YUY2ToARGBRow_AVX2, 1, 4, 4, 31) +ANY11C(UYVYToARGBRow_Any_AVX2, UYVYToARGBRow_AVX2, 1, 4, 4, 31) +#endif +#if defined(HAS_YUY2TOARGBROW_NEON) +ANY11C(YUY2ToARGBRow_Any_NEON, YUY2ToARGBRow_NEON, 1, 4, 4, 7) +ANY11C(UYVYToARGBRow_Any_NEON, UYVYToARGBRow_NEON, 1, 4, 4, 7) +#endif +#undef ANY11C + +// Any 1 to 1 blended. +#define ANY11B(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_ptr, int width) { \ + SIMD_ALIGNED(uint8 temp[128 * 2]); \ + memset(temp, 0, 128 * 2); /* for YUY2 and msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_ptr, n); \ + } \ + memcpy(temp, src_ptr + (n >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \ + memcpy(temp + 128, dst_ptr + n * BPP, r * BPP); \ + ANY_SIMD(temp, temp + 128, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ + } + +#ifdef HAS_ARGBCOPYALPHAROW_AVX2 +ANY11B(ARGBCopyAlphaRow_Any_AVX2, ARGBCopyAlphaRow_AVX2, 0, 4, 4, 15) +#endif +#ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2 +ANY11B(ARGBCopyAlphaRow_Any_SSE2, ARGBCopyAlphaRow_SSE2, 0, 4, 4, 7) +#endif +#ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2 +ANY11B(ARGBCopyYToAlphaRow_Any_AVX2, ARGBCopyYToAlphaRow_AVX2, 0, 1, 4, 15) +#endif +#ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2 +ANY11B(ARGBCopyYToAlphaRow_Any_SSE2, ARGBCopyYToAlphaRow_SSE2, 0, 1, 4, 7) +#endif +#undef ANY11B + +// Any 1 to 1 with parameter. +#define ANY11P(NAMEANY, ANY_SIMD, T, SBPP, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_ptr, \ + T shuffler, int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 2]); \ + memset(temp, 0, 64); /* for msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_ptr, shuffler, n); \ + } \ + memcpy(temp, src_ptr + n * SBPP, r * SBPP); \ + ANY_SIMD(temp, temp + 64, shuffler, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 64, r * BPP); \ + } + +#if defined(HAS_ARGBTORGB565DITHERROW_SSE2) +ANY11P(ARGBToRGB565DitherRow_Any_SSE2, ARGBToRGB565DitherRow_SSE2, + const uint32, 4, 2, 3) +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_AVX2) +ANY11P(ARGBToRGB565DitherRow_Any_AVX2, ARGBToRGB565DitherRow_AVX2, + const uint32, 4, 2, 7) +#endif +#if defined(HAS_ARGBTORGB565DITHERROW_NEON) +ANY11P(ARGBToRGB565DitherRow_Any_NEON, ARGBToRGB565DitherRow_NEON, + const uint32, 4, 2, 7) +#endif #ifdef HAS_ARGBSHUFFLEROW_SSE2 -YANY(ARGBShuffleRow_Any_SSE2, ARGBShuffleRow_SSE2, - ARGBShuffleRow_C, 4, 4, 3) +ANY11P(ARGBShuffleRow_Any_SSE2, ARGBShuffleRow_SSE2, const uint8*, 4, 4, 3) #endif #ifdef HAS_ARGBSHUFFLEROW_SSSE3 -YANY(ARGBShuffleRow_Any_SSSE3, ARGBShuffleRow_Unaligned_SSSE3, - ARGBShuffleRow_C, 4, 4, 7) +ANY11P(ARGBShuffleRow_Any_SSSE3, ARGBShuffleRow_SSSE3, const uint8*, 4, 4, 7) #endif #ifdef HAS_ARGBSHUFFLEROW_AVX2 -YANY(ARGBShuffleRow_Any_AVX2, ARGBShuffleRow_AVX2, - ARGBShuffleRow_C, 4, 4, 15) +ANY11P(ARGBShuffleRow_Any_AVX2, ARGBShuffleRow_AVX2, const uint8*, 4, 4, 15) #endif #ifdef HAS_ARGBSHUFFLEROW_NEON -YANY(ARGBShuffleRow_Any_NEON, ARGBShuffleRow_NEON, - ARGBShuffleRow_C, 4, 4, 3) +ANY11P(ARGBShuffleRow_Any_NEON, ARGBShuffleRow_NEON, const uint8*, 4, 4, 3) #endif -#undef YANY +#undef ANY11P -// Interpolate may want to work in place, so last16 method can not be used. -#define NANY(NAMEANY, TERP_SIMD, TERP_C, SBPP, BPP, MASK) \ +// Any 1 to 1 interpolate. Takes 2 rows of source via stride. +#define ANY11T(NAMEANY, ANY_SIMD, SBPP, BPP, MASK) \ void NAMEANY(uint8* dst_ptr, const uint8* src_ptr, \ ptrdiff_t src_stride_ptr, int width, \ int source_y_fraction) { \ + SIMD_ALIGNED(uint8 temp[64 * 3]); \ + memset(temp, 0, 64 * 2); /* for msan */ \ + int r = width & MASK; \ int n = width & ~MASK; \ - TERP_SIMD(dst_ptr, src_ptr, src_stride_ptr, \ - n, source_y_fraction); \ - TERP_C(dst_ptr + n * BPP, \ - src_ptr + n * SBPP, src_stride_ptr, \ - width & MASK, source_y_fraction); \ + if (n > 0) { \ + ANY_SIMD(dst_ptr, src_ptr, src_stride_ptr, n, source_y_fraction); \ + } \ + memcpy(temp, src_ptr + n * SBPP, r * SBPP); \ + memcpy(temp + 64, src_ptr + src_stride_ptr + n * SBPP, r * SBPP); \ + ANY_SIMD(temp + 128, temp, 64, MASK + 1, source_y_fraction); \ + memcpy(dst_ptr + n * BPP, temp + 128, r * BPP); \ } #ifdef HAS_INTERPOLATEROW_AVX2 -NANY(InterpolateRow_Any_AVX2, InterpolateRow_AVX2, - InterpolateRow_C, 1, 1, 32) +ANY11T(InterpolateRow_Any_AVX2, InterpolateRow_AVX2, 1, 1, 31) #endif #ifdef HAS_INTERPOLATEROW_SSSE3 -NANY(InterpolateRow_Any_SSSE3, InterpolateRow_Unaligned_SSSE3, - InterpolateRow_C, 1, 1, 15) -#endif -#ifdef HAS_INTERPOLATEROW_SSE2 -NANY(InterpolateRow_Any_SSE2, InterpolateRow_Unaligned_SSE2, - InterpolateRow_C, 1, 1, 15) +ANY11T(InterpolateRow_Any_SSSE3, InterpolateRow_SSSE3, 1, 1, 15) #endif #ifdef HAS_INTERPOLATEROW_NEON -NANY(InterpolateRow_Any_NEON, InterpolateRow_NEON, - InterpolateRow_C, 1, 1, 15) +ANY11T(InterpolateRow_Any_NEON, InterpolateRow_NEON, 1, 1, 15) #endif #ifdef HAS_INTERPOLATEROW_MIPS_DSPR2 -NANY(InterpolateRow_Any_MIPS_DSPR2, InterpolateRow_MIPS_DSPR2, - InterpolateRow_C, 1, 1, 3) +ANY11T(InterpolateRow_Any_MIPS_DSPR2, InterpolateRow_MIPS_DSPR2, 1, 1, 3) #endif -#undef NANY +#undef ANY11T + +// Any 1 to 1 mirror. +#define ANY11M(NAMEANY, ANY_SIMD, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_ptr, int width) { \ + SIMD_ALIGNED(uint8 temp[64 * 2]); \ + memset(temp, 0, 64); /* for msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr + r * BPP, dst_ptr, n); \ + } \ + memcpy(temp, src_ptr, r * BPP); \ + ANY_SIMD(temp, temp + 64, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp + 64 + (MASK + 1 - r) * BPP, r * BPP); \ + } + +#ifdef HAS_MIRRORROW_AVX2 +ANY11M(MirrorRow_Any_AVX2, MirrorRow_AVX2, 1, 31) +#endif +#ifdef HAS_MIRRORROW_SSSE3 +ANY11M(MirrorRow_Any_SSSE3, MirrorRow_SSSE3, 1, 15) +#endif +#ifdef HAS_MIRRORROW_NEON +ANY11M(MirrorRow_Any_NEON, MirrorRow_NEON, 1, 15) +#endif +#ifdef HAS_ARGBMIRRORROW_AVX2 +ANY11M(ARGBMirrorRow_Any_AVX2, ARGBMirrorRow_AVX2, 4, 7) +#endif +#ifdef HAS_ARGBMIRRORROW_SSE2 +ANY11M(ARGBMirrorRow_Any_SSE2, ARGBMirrorRow_SSE2, 4, 3) +#endif +#ifdef HAS_ARGBMIRRORROW_NEON +ANY11M(ARGBMirrorRow_Any_NEON, ARGBMirrorRow_NEON, 4, 3) +#endif +#undef ANY11M + +// Any 1 plane. (memset) +#define ANY1(NAMEANY, ANY_SIMD, T, BPP, MASK) \ + void NAMEANY(uint8* dst_ptr, T v32, int width) { \ + SIMD_ALIGNED(uint8 temp[64]); \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(dst_ptr, v32, n); \ + } \ + ANY_SIMD(temp, v32, MASK + 1); \ + memcpy(dst_ptr + n * BPP, temp, r * BPP); \ + } + +#ifdef HAS_SETROW_X86 +ANY1(SetRow_Any_X86, SetRow_X86, uint8, 1, 3) +#endif +#ifdef HAS_SETROW_NEON +ANY1(SetRow_Any_NEON, SetRow_NEON, uint8, 1, 15) +#endif +#ifdef HAS_ARGBSETROW_NEON +ANY1(ARGBSetRow_Any_NEON, ARGBSetRow_NEON, uint32, 4, 3) +#endif +#undef ANY1 + +// Any 1 to 2. Outputs UV planes. +#define ANY12(NAMEANY, ANY_SIMD, UVSHIFT, BPP, DUVSHIFT, MASK) \ + void NAMEANY(const uint8* src_ptr, uint8* dst_u, uint8* dst_v, int width) {\ + SIMD_ALIGNED(uint8 temp[128 * 3]); \ + memset(temp, 0, 128); /* for msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_u, dst_v, n); \ + } \ + memcpy(temp, src_ptr + (n >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \ + /* repeat last 4 bytes for 422 subsampler */ \ + if ((width & 1) && BPP == 4 && DUVSHIFT == 1) { \ + memcpy(temp + SS(r, UVSHIFT) * BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP, BPP); \ + } \ + /* repeat last 4 - 12 bytes for 411 subsampler */ \ + if (((width & 3) == 1) && BPP == 4 && DUVSHIFT == 2) { \ + memcpy(temp + SS(r, UVSHIFT) * BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP, BPP); \ + memcpy(temp + SS(r, UVSHIFT) * BPP + BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP, BPP * 2); \ + } \ + if (((width & 3) == 2) && BPP == 4 && DUVSHIFT == 2) { \ + memcpy(temp + SS(r, UVSHIFT) * BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP * 2, BPP * 2); \ + } \ + if (((width & 3) == 3) && BPP == 4 && DUVSHIFT == 2) { \ + memcpy(temp + SS(r, UVSHIFT) * BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP, BPP); \ + } \ + ANY_SIMD(temp, temp + 128, temp + 256, MASK + 1); \ + memcpy(dst_u + (n >> DUVSHIFT), temp + 128, SS(r, DUVSHIFT)); \ + memcpy(dst_v + (n >> DUVSHIFT), temp + 256, SS(r, DUVSHIFT)); \ + } + +#ifdef HAS_SPLITUVROW_SSE2 +ANY12(SplitUVRow_Any_SSE2, SplitUVRow_SSE2, 0, 2, 0, 15) +#endif +#ifdef HAS_SPLITUVROW_AVX2 +ANY12(SplitUVRow_Any_AVX2, SplitUVRow_AVX2, 0, 2, 0, 31) +#endif +#ifdef HAS_SPLITUVROW_NEON +ANY12(SplitUVRow_Any_NEON, SplitUVRow_NEON, 0, 2, 0, 15) +#endif +#ifdef HAS_SPLITUVROW_MIPS_DSPR2 +ANY12(SplitUVRow_Any_MIPS_DSPR2, SplitUVRow_MIPS_DSPR2, 0, 2, 0, 15) +#endif +#ifdef HAS_ARGBTOUV444ROW_SSSE3 +ANY12(ARGBToUV444Row_Any_SSSE3, ARGBToUV444Row_SSSE3, 0, 4, 0, 15) +#endif +#ifdef HAS_YUY2TOUV422ROW_AVX2 +ANY12(YUY2ToUV422Row_Any_AVX2, YUY2ToUV422Row_AVX2, 1, 4, 1, 31) +ANY12(UYVYToUV422Row_Any_AVX2, UYVYToUV422Row_AVX2, 1, 4, 1, 31) +#endif +#ifdef HAS_ARGBTOUV422ROW_SSSE3 +ANY12(ARGBToUV422Row_Any_SSSE3, ARGBToUV422Row_SSSE3, 0, 4, 1, 15) +#endif +#ifdef HAS_YUY2TOUV422ROW_SSE2 +ANY12(YUY2ToUV422Row_Any_SSE2, YUY2ToUV422Row_SSE2, 1, 4, 1, 15) +ANY12(UYVYToUV422Row_Any_SSE2, UYVYToUV422Row_SSE2, 1, 4, 1, 15) +#endif +#ifdef HAS_YUY2TOUV422ROW_NEON +ANY12(ARGBToUV444Row_Any_NEON, ARGBToUV444Row_NEON, 0, 4, 0, 7) +ANY12(ARGBToUV422Row_Any_NEON, ARGBToUV422Row_NEON, 0, 4, 1, 15) +ANY12(ARGBToUV411Row_Any_NEON, ARGBToUV411Row_NEON, 0, 4, 2, 31) +ANY12(YUY2ToUV422Row_Any_NEON, YUY2ToUV422Row_NEON, 1, 4, 1, 15) +ANY12(UYVYToUV422Row_Any_NEON, UYVYToUV422Row_NEON, 1, 4, 1, 15) +#endif +#undef ANY12 + +// Any 1 to 2 with source stride (2 rows of source). Outputs UV planes. +// 128 byte row allows for 32 avx ARGB pixels. +#define ANY12S(NAMEANY, ANY_SIMD, UVSHIFT, BPP, MASK) \ + void NAMEANY(const uint8* src_ptr, int src_stride_ptr, \ + uint8* dst_u, uint8* dst_v, int width) { \ + SIMD_ALIGNED(uint8 temp[128 * 4]); \ + memset(temp, 0, 128 * 2); /* for msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, src_stride_ptr, dst_u, dst_v, n); \ + } \ + memcpy(temp, src_ptr + (n >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \ + memcpy(temp + 128, src_ptr + src_stride_ptr + (n >> UVSHIFT) * BPP, \ + SS(r, UVSHIFT) * BPP); \ + if ((width & 1) && UVSHIFT == 0) { /* repeat last pixel for subsample */\ + memcpy(temp + SS(r, UVSHIFT) * BPP, \ + temp + SS(r, UVSHIFT) * BPP - BPP, BPP); \ + memcpy(temp + 128 + SS(r, UVSHIFT) * BPP, \ + temp + 128 + SS(r, UVSHIFT) * BPP - BPP, BPP); \ + } \ + ANY_SIMD(temp, 128, temp + 256, temp + 384, MASK + 1); \ + memcpy(dst_u + (n >> 1), temp + 256, SS(r, 1)); \ + memcpy(dst_v + (n >> 1), temp + 384, SS(r, 1)); \ + } + +#ifdef HAS_ARGBTOUVROW_AVX2 +ANY12S(ARGBToUVRow_Any_AVX2, ARGBToUVRow_AVX2, 0, 4, 31) +#endif +#ifdef HAS_ARGBTOUVROW_SSSE3 +ANY12S(ARGBToUVRow_Any_SSSE3, ARGBToUVRow_SSSE3, 0, 4, 15) +ANY12S(ARGBToUVJRow_Any_SSSE3, ARGBToUVJRow_SSSE3, 0, 4, 15) +ANY12S(BGRAToUVRow_Any_SSSE3, BGRAToUVRow_SSSE3, 0, 4, 15) +ANY12S(ABGRToUVRow_Any_SSSE3, ABGRToUVRow_SSSE3, 0, 4, 15) +ANY12S(RGBAToUVRow_Any_SSSE3, RGBAToUVRow_SSSE3, 0, 4, 15) +#endif +#ifdef HAS_YUY2TOUVROW_AVX2 +ANY12S(YUY2ToUVRow_Any_AVX2, YUY2ToUVRow_AVX2, 1, 4, 31) +ANY12S(UYVYToUVRow_Any_AVX2, UYVYToUVRow_AVX2, 1, 4, 31) +#endif +#ifdef HAS_YUY2TOUVROW_SSE2 +ANY12S(YUY2ToUVRow_Any_SSE2, YUY2ToUVRow_SSE2, 1, 4, 15) +ANY12S(UYVYToUVRow_Any_SSE2, UYVYToUVRow_SSE2, 1, 4, 15) +#endif +#ifdef HAS_ARGBTOUVROW_NEON +ANY12S(ARGBToUVRow_Any_NEON, ARGBToUVRow_NEON, 0, 4, 15) +#endif +#ifdef HAS_ARGBTOUVJROW_NEON +ANY12S(ARGBToUVJRow_Any_NEON, ARGBToUVJRow_NEON, 0, 4, 15) +#endif +#ifdef HAS_BGRATOUVROW_NEON +ANY12S(BGRAToUVRow_Any_NEON, BGRAToUVRow_NEON, 0, 4, 15) +#endif +#ifdef HAS_ABGRTOUVROW_NEON +ANY12S(ABGRToUVRow_Any_NEON, ABGRToUVRow_NEON, 0, 4, 15) +#endif +#ifdef HAS_RGBATOUVROW_NEON +ANY12S(RGBAToUVRow_Any_NEON, RGBAToUVRow_NEON, 0, 4, 15) +#endif +#ifdef HAS_RGB24TOUVROW_NEON +ANY12S(RGB24ToUVRow_Any_NEON, RGB24ToUVRow_NEON, 0, 3, 15) +#endif +#ifdef HAS_RAWTOUVROW_NEON +ANY12S(RAWToUVRow_Any_NEON, RAWToUVRow_NEON, 0, 3, 15) +#endif +#ifdef HAS_RGB565TOUVROW_NEON +ANY12S(RGB565ToUVRow_Any_NEON, RGB565ToUVRow_NEON, 0, 2, 15) +#endif +#ifdef HAS_ARGB1555TOUVROW_NEON +ANY12S(ARGB1555ToUVRow_Any_NEON, ARGB1555ToUVRow_NEON, 0, 2, 15) +#endif +#ifdef HAS_ARGB4444TOUVROW_NEON +ANY12S(ARGB4444ToUVRow_Any_NEON, ARGB4444ToUVRow_NEON, 0, 2, 15) +#endif +#ifdef HAS_YUY2TOUVROW_NEON +ANY12S(YUY2ToUVRow_Any_NEON, YUY2ToUVRow_NEON, 1, 4, 15) +#endif +#ifdef HAS_UYVYTOUVROW_NEON +ANY12S(UYVYToUVRow_Any_NEON, UYVYToUVRow_NEON, 1, 4, 15) +#endif +#undef ANY12S #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/row_common.cc b/TMessagesProj/jni/libyuv/source/row_common.cc index fa2b752a..c820cdf1 100644 --- a/TMessagesProj/jni/libyuv/source/row_common.cc +++ b/TMessagesProj/jni/libyuv/source/row_common.cc @@ -100,6 +100,20 @@ void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int width) { } } +void RAWToRGB24Row_C(const uint8* src_raw, uint8* dst_rgb24, int width) { + int x; + for (x = 0; x < width; ++x) { + uint8 r = src_raw[0]; + uint8 g = src_raw[1]; + uint8 b = src_raw[2]; + dst_rgb24[0] = b; + dst_rgb24[1] = g; + dst_rgb24[2] = r; + dst_rgb24 += 3; + src_raw += 3; + } +} + void RGB565ToARGBRow_C(const uint8* src_rgb565, uint8* dst_argb, int width) { int x; for (x = 0; x < width; ++x) { @@ -199,6 +213,40 @@ void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { } } +// dither4 is a row of 4 values from 4x4 dither matrix. +// The 4x4 matrix contains values to increase RGB. When converting to +// fewer bits (565) this provides an ordered dither. +// The order in the 4x4 matrix in first byte is upper left. +// The 4 values are passed as an int, then referenced as an array, so +// endian will not affect order of the original matrix. But the dither4 +// will containing the first pixel in the lower byte for little endian +// or the upper byte for big endian. +void ARGBToRGB565DitherRow_C(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + int dither0 = ((const unsigned char*)(&dither4))[x & 3]; + int dither1 = ((const unsigned char*)(&dither4))[(x + 1) & 3]; + uint8 b0 = clamp255(src_argb[0] + dither0) >> 3; + uint8 g0 = clamp255(src_argb[1] + dither0) >> 2; + uint8 r0 = clamp255(src_argb[2] + dither0) >> 3; + uint8 b1 = clamp255(src_argb[4] + dither1) >> 3; + uint8 g1 = clamp255(src_argb[5] + dither1) >> 2; + uint8 r1 = clamp255(src_argb[6] + dither1) >> 3; + WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | + (b1 << 16) | (g1 << 21) | (r1 << 27)); + dst_rgb += 4; + src_argb += 8; + } + if (width & 1) { + int dither0 = ((const unsigned char*)(&dither4))[(width - 1) & 3]; + uint8 b0 = clamp255(src_argb[0] + dither0) >> 3; + uint8 g0 = clamp255(src_argb[1] + dither0) >> 2; + uint8 r0 = clamp255(src_argb[2] + dither0) >> 3; + *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); + } +} + void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { int x; for (x = 0; x < width - 1; x += 2) { @@ -385,6 +433,28 @@ void NAME ## ToUVJRow_C(const uint8* src_rgb0, int src_stride_rgb, \ MAKEROWYJ(ARGB, 2, 1, 0, 4) #undef MAKEROWYJ +void ARGBToUVJ422Row_C(const uint8* src_argb, + uint8* dst_u, uint8* dst_v, int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + uint8 ab = (src_argb[0] + src_argb[4]) >> 1; + uint8 ag = (src_argb[1] + src_argb[5]) >> 1; + uint8 ar = (src_argb[2] + src_argb[6]) >> 1; + dst_u[0] = RGBToUJ(ar, ag, ab); + dst_v[0] = RGBToVJ(ar, ag, ab); + src_argb += 8; + dst_u += 1; + dst_v += 1; + } + if (width & 1) { + uint8 ab = src_argb[0]; + uint8 ag = src_argb[1]; + uint8 ar = src_argb[2]; + dst_u[0] = RGBToUJ(ar, ag, ab); + dst_v[0] = RGBToVJ(ar, ag, ab); + } +} + void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int width) { int x; for (x = 0; x < width; ++x) { @@ -623,10 +693,11 @@ void ARGBToUV411Row_C(const uint8* src_argb, dst_u += 1; dst_v += 1; } + // Odd width handling mimics 'any' function which replicates last pixel. if ((width & 3) == 3) { - uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8]) / 3; - uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9]) / 3; - uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10]) / 3; + uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8] + src_argb[8]) >> 2; + uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9] + src_argb[9]) >> 2; + uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10] + src_argb[10]) >> 2; dst_u[0] = RGBToU(ar, ag, ab); dst_v[0] = RGBToV(ar, ag, ab); } else if ((width & 3) == 2) { @@ -926,7 +997,7 @@ void SobelXYRow_C(const uint8* src_sobelx, const uint8* src_sobely, } } -void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { +void J400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { // Copy a Y to RGB. int x; for (x = 0; x < width; ++x) { @@ -938,47 +1009,344 @@ void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { } } +// TODO(fbarchard): Unify these structures to be platform independent. +// TODO(fbarchard): Generate SIMD structures from float matrix. + +// BT.601 YUV to RGB reference +// R = (Y - 16) * 1.164 - V * -1.596 +// G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 +// B = (Y - 16) * 1.164 - U * -2.018 + +// Y contribution to R,G,B. Scale and bias. +#define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ +#define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ + +// U and V contributions to R,G,B. +#define UB -128 /* max(-128, round(-2.018 * 64)) */ +#define UG 25 /* round(0.391 * 64) */ +#define VG 52 /* round(0.813 * 64) */ +#define VR -102 /* round(-1.596 * 64) */ + +// Bias values to subtract 16 from Y and 128 from U and V. +#define BB (UB * 128 + YGB) +#define BG (UG * 128 + VG * 128 + YGB) +#define BR (VR * 128 + YGB) + +#if defined(__aarch64__) +const YuvConstants SIMD_ALIGNED(kYuvI601Constants) = { + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuI601Constants) = { + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#elif defined(__arm__) +const YuvConstants SIMD_ALIGNED(kYuvI601Constants) = { + { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, + { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuI601Constants) = { + { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, + { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#else +const YuvConstants SIMD_ALIGNED(kYuvI601Constants) = { + { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, + UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, + { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, + UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, + { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, + 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +const YuvConstants SIMD_ALIGNED(kYvuI601Constants) = { + { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, + VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0 }, + { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, + VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, + { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, + 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +#endif + +#undef BB +#undef BG +#undef BR +#undef YGB +#undef UB +#undef UG +#undef VG +#undef VR +#undef YG + +// JPEG YUV to RGB reference +// * R = Y - V * -1.40200 +// * G = Y - U * 0.34414 - V * 0.71414 +// * B = Y - U * -1.77200 + +// Y contribution to R,G,B. Scale and bias. +#define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ +#define YGB 32 /* 64 / 2 */ + +// U and V contributions to R,G,B. +#define UB -113 /* round(-1.77200 * 64) */ +#define UG 22 /* round(0.34414 * 64) */ +#define VG 46 /* round(0.71414 * 64) */ +#define VR -90 /* round(-1.40200 * 64) */ + +// Bias values to round, and subtract 128 from U and V. +#define BB (UB * 128 + YGB) +#define BG (UG * 128 + VG * 128 + YGB) +#define BR (VR * 128 + YGB) + +#if defined(__aarch64__) +const YuvConstants SIMD_ALIGNED(kYuvJPEGConstants) = { + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuJPEGConstants) = { + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#elif defined(__arm__) +const YuvConstants SIMD_ALIGNED(kYuvJPEGConstants) = { + { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, + { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuJPEGConstants) = { + { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, + { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#else +const YuvConstants SIMD_ALIGNED(kYuvJPEGConstants) = { + { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, + UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, + { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, + UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, + { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, + 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +const YuvConstants SIMD_ALIGNED(kYvuJPEGConstants) = { + { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, + VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0 }, + { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, + VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, + { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, + 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +#endif + +#undef BB +#undef BG +#undef BR +#undef YGB +#undef UB +#undef UG +#undef VG +#undef VR +#undef YG + +// BT.709 YUV to RGB reference +// * R = Y - V * -1.28033 +// * G = Y - U * 0.21482 - V * 0.38059 +// * B = Y - U * -2.12798 + +// Y contribution to R,G,B. Scale and bias. +#define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ +#define YGB 32 /* 64 / 2 */ + +// TODO(fbarchard): Find way to express 2.12 instead of 2.0. +// U and V contributions to R,G,B. +#define UB -128 /* max(-128, round(-2.12798 * 64)) */ +#define UG 14 /* round(0.21482 * 64) */ +#define VG 24 /* round(0.38059 * 64) */ +#define VR -82 /* round(-1.28033 * 64) */ + +// Bias values to round, and subtract 128 from U and V. +#define BB (UB * 128 + YGB) +#define BG (UG * 128 + VG * 128 + YGB) +#define BR (VR * 128 + YGB) + +#if defined(__aarch64__) +const YuvConstants SIMD_ALIGNED(kYuvH709Constants) = { + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { UG, VG, UG, VG, UG, VG, UG, VG }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuH709Constants) = { + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { VG, UG, VG, UG, VG, UG, VG, UG }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#elif defined(__arm__) +const YuvConstants SIMD_ALIGNED(kYuvH709Constants) = { + { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, + { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BB, BG, BR, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +const YuvConstants SIMD_ALIGNED(kYvuH709Constants) = { + { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, + { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, + { BR, BG, BB, 0, 0, 0, 0, 0 }, + { 0x0101 * YG, 0, 0, 0 } +}; +#else +const YuvConstants SIMD_ALIGNED(kYuvH709Constants) = { + { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, + UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, + { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, + UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, + { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, + 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +const YuvConstants SIMD_ALIGNED(kYvuH709Constants) = { + { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, + VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0 }, + { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, + VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, + { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, + 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB }, + { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, + { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, + { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, + { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } +}; +#endif + +#undef BB +#undef BG +#undef BR +#undef YGB +#undef UB +#undef UG +#undef VG +#undef VR +#undef YG + // C reference code that mimics the YUV assembly. - -#define YG 74 /* (int8)(1.164 * 64 + 0.5) */ - -#define UB 127 /* min(63,(int8)(2.018 * 64)) */ -#define UG -25 /* (int8)(-0.391 * 64 - 0.5) */ -#define UR 0 - -#define VB 0 -#define VG -52 /* (int8)(-0.813 * 64 - 0.5) */ -#define VR 102 /* (int8)(1.596 * 64 + 0.5) */ - -// Bias -#define BB UB * 128 + VB * 128 -#define BG UG * 128 + VG * 128 -#define BR UR * 128 + VR * 128 - static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, - uint8* b, uint8* g, uint8* r) { - int32 y1 = ((int32)(y) - 16) * YG; - *b = Clamp((int32)((u * UB + v * VB) - (BB) + y1) >> 6); - *g = Clamp((int32)((u * UG + v * VG) - (BG) + y1) >> 6); - *r = Clamp((int32)((u * UR + v * VR) - (BR) + y1) >> 6); + uint8* b, uint8* g, uint8* r, + const struct YuvConstants* yuvconstants) { +#if defined(__aarch64__) + int ub = -yuvconstants->kUVToRB[0]; + int ug = yuvconstants->kUVToG[0]; + int vg = yuvconstants->kUVToG[1]; + int vr = -yuvconstants->kUVToRB[1]; + int bb = yuvconstants->kUVBiasBGR[0]; + int bg = yuvconstants->kUVBiasBGR[1]; + int br = yuvconstants->kUVBiasBGR[2]; + int yg = yuvconstants->kYToRgb[0] / 0x0101; +#elif defined(__arm__) + int ub = -yuvconstants->kUVToRB[0]; + int ug = yuvconstants->kUVToG[0]; + int vg = yuvconstants->kUVToG[4]; + int vr = -yuvconstants->kUVToRB[4]; + int bb = yuvconstants->kUVBiasBGR[0]; + int bg = yuvconstants->kUVBiasBGR[1]; + int br = yuvconstants->kUVBiasBGR[2]; + int yg = yuvconstants->kYToRgb[0] / 0x0101; +#else + int ub = yuvconstants->kUVToB[0]; + int ug = yuvconstants->kUVToG[0]; + int vg = yuvconstants->kUVToG[1]; + int vr = yuvconstants->kUVToR[1]; + int bb = yuvconstants->kUVBiasB[0]; + int bg = yuvconstants->kUVBiasG[0]; + int br = yuvconstants->kUVBiasR[0]; + int yg = yuvconstants->kYToRgb[0]; +#endif + + uint32 y1 = (uint32)(y * 0x0101 * yg) >> 16; + *b = Clamp((int32)(-(u * ub ) + y1 + bb) >> 6); + *g = Clamp((int32)(-(u * ug + v * vg) + y1 + bg) >> 6); + *r = Clamp((int32)(-( v * vr) + y1 + br) >> 6); } +// Y contribution to R,G,B. Scale and bias. +#define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ +#define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ + +// C reference code that mimics the YUV assembly. +static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) { + uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; + *b = Clamp((int32)(y1 + YGB) >> 6); + *g = Clamp((int32)(y1 + YGB) >> 6); + *r = Clamp((int32)(y1 + YGB) >> 6); +} + +#undef YG +#undef YGB + #if !defined(LIBYUV_DISABLE_NEON) && \ - (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) + (defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON)) // C mimic assembly. // TODO(fbarchard): Remove subsampling from Neon. void I444ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { uint8 u = (src_u[0] + src_u[1] + 1) >> 1; uint8 v = (src_v[0] + src_v[1] + 1) >> 1; - YuvPixel(src_y[0], u, v, rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + YuvPixel(src_y[0], u, v, rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, + yuvconstants); rgb_buf[3] = 255; - YuvPixel(src_y[1], u, v, rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + YuvPixel(src_y[1], u, v, rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, + yuvconstants); rgb_buf[7] = 255; src_y += 2; src_u += 2; @@ -987,7 +1355,8 @@ void I444ToARGBRow_C(const uint8* src_y, } if (width & 1) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); + rgb_buf[3] = 255; } } #else @@ -995,11 +1364,12 @@ void I444ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width; ++x) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; src_y += 1; src_u += 1; @@ -1008,19 +1378,21 @@ void I444ToARGBRow_C(const uint8* src_y, } } #endif + // Also used for 420 void I422ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; src_y += 2; src_u += 1; @@ -1029,22 +1401,51 @@ void I422ToARGBRow_C(const uint8* src_y, } if (width & 1) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } +void I422AlphaToARGBRow_C(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + const uint8* src_a, + uint8* rgb_buf, + const struct YuvConstants* yuvconstants, + int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + YuvPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); + rgb_buf[3] = src_a[0]; + YuvPixel(src_y[1], src_u[0], src_v[0], + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); + rgb_buf[7] = src_a[1]; + src_y += 2; + src_u += 1; + src_v += 1; + src_a += 2; + rgb_buf += 8; // Advance 2 pixels. + } + if (width & 1) { + YuvPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); + rgb_buf[3] = src_a[0]; + } +} + void I422ToRGB24Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 3, rgb_buf + 4, rgb_buf + 5); + rgb_buf + 3, rgb_buf + 4, rgb_buf + 5, yuvconstants); src_y += 2; src_u += 1; src_v += 1; @@ -1052,29 +1453,7 @@ void I422ToRGB24Row_C(const uint8* src_y, } if (width & 1) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); - } -} - -void I422ToRAWRow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - int x; - for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); - YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 5, rgb_buf + 4, rgb_buf + 3); - src_y += 2; - src_u += 1; - src_v += 1; - rgb_buf += 6; // Advance 2 pixels. - } - if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); } } @@ -1082,6 +1461,7 @@ void I422ToARGB4444Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width) { uint8 b0; uint8 g0; @@ -1091,8 +1471,8 @@ void I422ToARGB4444Row_C(const uint8* src_y, uint8 r1; int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); - YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); + YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1, yuvconstants); b0 = b0 >> 4; g0 = g0 >> 4; r0 = r0 >> 4; @@ -1107,7 +1487,7 @@ void I422ToARGB4444Row_C(const uint8* src_y, dst_argb4444 += 4; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); b0 = b0 >> 4; g0 = g0 >> 4; r0 = r0 >> 4; @@ -1120,6 +1500,7 @@ void I422ToARGB1555Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, int width) { uint8 b0; uint8 g0; @@ -1129,8 +1510,8 @@ void I422ToARGB1555Row_C(const uint8* src_y, uint8 r1; int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); - YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); + YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 3; r0 = r0 >> 3; @@ -1145,7 +1526,7 @@ void I422ToARGB1555Row_C(const uint8* src_y, dst_argb1555 += 4; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 3; r0 = r0 >> 3; @@ -1158,6 +1539,7 @@ void I422ToRGB565Row_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { uint8 b0; uint8 g0; @@ -1167,8 +1549,8 @@ void I422ToRGB565Row_C(const uint8* src_y, uint8 r1; int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); - YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); + YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 2; r0 = r0 >> 3; @@ -1183,7 +1565,7 @@ void I422ToRGB565Row_C(const uint8* src_y, dst_rgb565 += 4; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); + YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 2; r0 = r0 >> 3; @@ -1195,20 +1577,21 @@ void I411ToARGBRow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 3; x += 4) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; YuvPixel(src_y[2], src_u[0], src_v[0], - rgb_buf + 8, rgb_buf + 9, rgb_buf + 10); + rgb_buf + 8, rgb_buf + 9, rgb_buf + 10, yuvconstants); rgb_buf[11] = 255; YuvPixel(src_y[3], src_u[0], src_v[0], - rgb_buf + 12, rgb_buf + 13, rgb_buf + 14); + rgb_buf + 12, rgb_buf + 13, rgb_buf + 14, yuvconstants); rgb_buf[15] = 255; src_y += 4; src_u += 1; @@ -1217,40 +1600,41 @@ void I411ToARGBRow_C(const uint8* src_y, } if (width & 2) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; src_y += 2; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } void NV12ToARGBRow_C(const uint8* src_y, - const uint8* usrc_v, + const uint8* src_uv, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], usrc_v[0], usrc_v[1], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + YuvPixel(src_y[0], src_uv[0], src_uv[1], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; - YuvPixel(src_y[1], usrc_v[0], usrc_v[1], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + YuvPixel(src_y[1], src_uv[0], src_uv[1], + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; src_y += 2; - usrc_v += 2; + src_uv += 2; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], usrc_v[0], usrc_v[1], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + YuvPixel(src_y[0], src_uv[0], src_uv[1], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } @@ -1258,31 +1642,31 @@ void NV12ToARGBRow_C(const uint8* src_y, void NV21ToARGBRow_C(const uint8* src_y, const uint8* src_vu, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_y[0], src_vu[1], src_vu[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; - YuvPixel(src_y[1], src_vu[1], src_vu[0], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; - src_y += 2; src_vu += 2; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { YuvPixel(src_y[0], src_vu[1], src_vu[0], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } void NV12ToRGB565Row_C(const uint8* src_y, - const uint8* usrc_v, + const uint8* src_uv, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { uint8 b0; uint8 g0; @@ -1292,8 +1676,8 @@ void NV12ToRGB565Row_C(const uint8* src_y, uint8 r1; int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); - YuvPixel(src_y[1], usrc_v[0], usrc_v[1], &b1, &g1, &r1); + YuvPixel(src_y[0], src_uv[0], src_uv[1], &b0, &g0, &r0, yuvconstants); + YuvPixel(src_y[1], src_uv[0], src_uv[1], &b1, &g1, &r1, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 2; r0 = r0 >> 3; @@ -1303,46 +1687,11 @@ void NV12ToRGB565Row_C(const uint8* src_y, *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | (b1 << 16) | (g1 << 21) | (r1 << 27); src_y += 2; - usrc_v += 2; + src_uv += 2; dst_rgb565 += 4; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); - b0 = b0 >> 3; - g0 = g0 >> 2; - r0 = r0 >> 3; - *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); - } -} - -void NV21ToRGB565Row_C(const uint8* src_y, - const uint8* vsrc_u, - uint8* dst_rgb565, - int width) { - uint8 b0; - uint8 g0; - uint8 r0; - uint8 b1; - uint8 g1; - uint8 r1; - int x; - for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0); - YuvPixel(src_y[1], vsrc_u[1], vsrc_u[0], &b1, &g1, &r1); - b0 = b0 >> 3; - g0 = g0 >> 2; - r0 = r0 >> 3; - b1 = b1 >> 3; - g1 = g1 >> 2; - r1 = r1 >> 3; - *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | - (b1 << 16) | (g1 << 21) | (r1 << 27); - src_y += 2; - vsrc_u += 2; - dst_rgb565 += 4; // Advance 2 pixels. - } - if (width & 1) { - YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0); + YuvPixel(src_y[0], src_uv[0], src_uv[1], &b0, &g0, &r0, yuvconstants); b0 = b0 >> 3; g0 = g0 >> 2; r0 = r0 >> 3; @@ -1352,92 +1701,44 @@ void NV21ToRGB565Row_C(const uint8* src_y, void YUY2ToARGBRow_C(const uint8* src_yuy2, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; YuvPixel(src_yuy2[2], src_yuy2[1], src_yuy2[3], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; src_yuy2 += 4; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } void UYVYToARGBRow_C(const uint8* src_uyvy, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; YuvPixel(src_uyvy[3], src_uyvy[0], src_uyvy[2], - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); rgb_buf[7] = 255; src_uyvy += 4; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); - rgb_buf[3] = 255; - } -} - -void I422ToBGRARow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - int x; - for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 3, rgb_buf + 2, rgb_buf + 1); - rgb_buf[0] = 255; - YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 7, rgb_buf + 6, rgb_buf + 5); - rgb_buf[4] = 255; - src_y += 2; - src_u += 1; - src_v += 1; - rgb_buf += 8; // Advance 2 pixels. - } - if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 3, rgb_buf + 2, rgb_buf + 1); - rgb_buf[0] = 255; - } -} - -void I422ToABGRRow_C(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - int x; - for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); - rgb_buf[3] = 255; - YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 6, rgb_buf + 5, rgb_buf + 4); - rgb_buf[7] = 255; - src_y += 2; - src_u += 1; - src_v += 1; - rgb_buf += 8; // Advance 2 pixels. - } - if (width & 1) { - YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); rgb_buf[3] = 255; } } @@ -1446,14 +1747,15 @@ void I422ToRGBARow_C(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { int x; for (x = 0; x < width - 1; x += 2) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); + rgb_buf + 1, rgb_buf + 2, rgb_buf + 3, yuvconstants); rgb_buf[0] = 255; YuvPixel(src_y[1], src_u[0], src_v[0], - rgb_buf + 5, rgb_buf + 6, rgb_buf + 7); + rgb_buf + 5, rgb_buf + 6, rgb_buf + 7, yuvconstants); rgb_buf[4] = 255; src_y += 2; src_u += 1; @@ -1462,26 +1764,23 @@ void I422ToRGBARow_C(const uint8* src_y, } if (width & 1) { YuvPixel(src_y[0], src_u[0], src_v[0], - rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); + rgb_buf + 1, rgb_buf + 2, rgb_buf + 3, yuvconstants); rgb_buf[0] = 255; } } -void YToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) { +void I400ToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) { int x; for (x = 0; x < width - 1; x += 2) { - YuvPixel(src_y[0], 128, 128, - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + YPixel(src_y[0], rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); rgb_buf[3] = 255; - YuvPixel(src_y[1], 128, 128, - rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + YPixel(src_y[1], rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); rgb_buf[7] = 255; src_y += 2; rgb_buf += 8; // Advance 2 pixels. } if (width & 1) { - YuvPixel(src_y[0], 128, 128, - rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + YPixel(src_y[0], rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); rgb_buf[3] = 255; } } @@ -1569,28 +1868,15 @@ void CopyRow_16_C(const uint16* src, uint16* dst, int count) { memcpy(dst, src, count * 2); } -void SetRow_C(uint8* dst, uint32 v8, int count) { -#ifdef _MSC_VER - // VC will generate rep stosb. - int x; - for (x = 0; x < count; ++x) { - dst[x] = v8; - } -#else - memset(dst, v8, count); -#endif +void SetRow_C(uint8* dst, uint8 v8, int width) { + memset(dst, v8, width); } -void ARGBSetRows_C(uint8* dst, uint32 v32, int width, - int dst_stride, int height) { - int y; - for (y = 0; y < height; ++y) { - uint32* d = (uint32*)(dst); - int x; - for (x = 0; x < width; ++x) { - d[x] = v32; - } - dst += dst_stride; +void ARGBSetRow_C(uint8* dst_argb, uint32 v32, int width) { + uint32* d = (uint32*)(dst_argb); + int x; + for (x = 0; x < width; ++x) { + d[x] = v32; } } @@ -1730,6 +2016,25 @@ void ARGBBlendRow_C(const uint8* src_argb0, const uint8* src_argb1, } } #undef BLEND + +#define UBLEND(f, b, a) (((a) * f) + ((255 - a) * b) + 255) >> 8 +void BlendPlaneRow_C(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + dst[0] = UBLEND(src0[0], src1[0], alpha[0]); + dst[1] = UBLEND(src0[1], src1[1], alpha[1]); + src0 += 2; + src1 += 2; + alpha += 2; + dst += 2; + } + if (width & 1) { + dst[0] = UBLEND(src0[0], src1[0], alpha[0]); + } +} +#undef UBLEND + #define ATTENUATE(f, a) (a | (a << 8)) * (f | (f << 8)) >> 24 // Multiply source RGB by alpha and store to destination. @@ -1885,19 +2190,19 @@ void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride, } } -// Blend 2 rows into 1 for conversions such as I422ToI420. -void HalfRow_C(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { +// Blend 2 rows into 1. +static void HalfRow_C(const uint8* src_uv, int src_uv_stride, + uint8* dst_uv, int width) { int x; - for (x = 0; x < pix; ++x) { + for (x = 0; x < width; ++x) { dst_uv[x] = (src_uv[x] + src_uv[src_uv_stride + x] + 1) >> 1; } } -void HalfRow_16_C(const uint16* src_uv, int src_uv_stride, - uint16* dst_uv, int pix) { +static void HalfRow_16_C(const uint16* src_uv, int src_uv_stride, + uint16* dst_uv, int width) { int x; - for (x = 0; x < pix; ++x) { + for (x = 0; x < width; ++x) { dst_uv[x] = (src_uv[x] + src_uv[src_uv_stride + x] + 1) >> 1; } } @@ -1906,27 +2211,30 @@ void HalfRow_16_C(const uint16* src_uv, int src_uv_stride, void InterpolateRow_C(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride, int width, int source_y_fraction) { - int y1_fraction = source_y_fraction; + int y1_fraction = source_y_fraction ; int y0_fraction = 256 - y1_fraction; const uint8* src_ptr1 = src_ptr + src_stride; int x; - if (source_y_fraction == 0) { + if (y1_fraction == 0) { memcpy(dst_ptr, src_ptr, width); return; } - if (source_y_fraction == 128) { + if (y1_fraction == 128) { HalfRow_C(src_ptr, (int)(src_stride), dst_ptr, width); return; } for (x = 0; x < width - 1; x += 2) { - dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; - dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8; + dst_ptr[0] = + (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction + 128) >> 8; + dst_ptr[1] = + (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction + 128) >> 8; src_ptr += 2; src_ptr1 += 2; dst_ptr += 2; } if (width & 1) { - dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; + dst_ptr[0] = + (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction + 128) >> 8; } } @@ -1957,50 +2265,16 @@ void InterpolateRow_16_C(uint16* dst_ptr, const uint16* src_ptr, } } -// Select 2 channels from ARGB on alternating pixels. e.g. BGBGBGBG -void ARGBToBayerRow_C(const uint8* src_argb, - uint8* dst_bayer, uint32 selector, int pix) { - int index0 = selector & 0xff; - int index1 = (selector >> 8) & 0xff; - // Copy a row of Bayer. - int x; - for (x = 0; x < pix - 1; x += 2) { - dst_bayer[0] = src_argb[index0]; - dst_bayer[1] = src_argb[index1]; - src_argb += 8; - dst_bayer += 2; - } - if (pix & 1) { - dst_bayer[0] = src_argb[index0]; - } -} - -// Select G channel from ARGB. e.g. GGGGGGGG -void ARGBToBayerGGRow_C(const uint8* src_argb, - uint8* dst_bayer, uint32 selector, int pix) { - // Copy a row of G. - int x; - for (x = 0; x < pix - 1; x += 2) { - dst_bayer[0] = src_argb[1]; - dst_bayer[1] = src_argb[5]; - src_argb += 8; - dst_bayer += 2; - } - if (pix & 1) { - dst_bayer[0] = src_argb[1]; - } -} - // Use first 4 shuffler values to reorder ARGB channels. void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { int index0 = shuffler[0]; int index1 = shuffler[1]; int index2 = shuffler[2]; int index3 = shuffler[3]; // Shuffle a row of ARGB. int x; - for (x = 0; x < pix; ++x) { + for (x = 0; x < width; ++x) { // To support in-place conversion. uint8 b = src_argb[index0]; uint8 g = src_argb[index1]; @@ -2033,7 +2307,7 @@ void I422ToYUY2Row_C(const uint8* src_y, if (width & 1) { dst_frame[0] = src_y[0]; dst_frame[1] = src_u[0]; - dst_frame[2] = src_y[0]; // duplicate last y + dst_frame[2] = 0; dst_frame[3] = src_v[0]; } } @@ -2057,130 +2331,14 @@ void I422ToUYVYRow_C(const uint8* src_y, dst_frame[0] = src_u[0]; dst_frame[1] = src_y[0]; dst_frame[2] = src_v[0]; - dst_frame[3] = src_y[0]; // duplicate last y + dst_frame[3] = 0; } } -#if !defined(LIBYUV_DISABLE_X86) && defined(HAS_I422TOARGBROW_SSSE3) -// row_win.cc has asm version, but GCC uses 2 step wrapper. -#if !defined(_MSC_VER) && (defined(__x86_64__) || defined(__i386__)) -void I422ToRGB565Row_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); - ARGBToRGB565Row_SSE2(row, rgb_buf, width); - free_aligned_buffer_64(row); -} -#endif // !defined(_MSC_VER) && (defined(__x86_64__) || defined(__i386__)) - -#if defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) -void I422ToARGB1555Row_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); - ARGBToARGB1555Row_SSE2(row, rgb_buf, width); - free_aligned_buffer_64(row); -} - -void I422ToARGB4444Row_SSSE3(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* rgb_buf, - int width) { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); - ARGBToARGB4444Row_SSE2(row, rgb_buf, width); - free_aligned_buffer_64(row); -} - -void NV12ToRGB565Row_SSSE3(const uint8* src_y, - const uint8* src_uv, - uint8* dst_rgb565, - int width) { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - NV12ToARGBRow_SSSE3(src_y, src_uv, row, width); - ARGBToRGB565Row_SSE2(row, dst_rgb565, width); - free_aligned_buffer_64(row); -} - -void NV21ToRGB565Row_SSSE3(const uint8* src_y, - const uint8* src_vu, - uint8* dst_rgb565, - int width) { - // Allocate a row of ARGB. - align_buffer_64(row, width * 4); - NV21ToARGBRow_SSSE3(src_y, src_vu, row, width); - ARGBToRGB565Row_SSE2(row, dst_rgb565, width); - free_aligned_buffer_64(row); -} - -void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2, - uint8* dst_argb, - int width) { - // Allocate a rows of yuv. - align_buffer_64(row_y, ((width + 63) & ~63) * 2); - uint8* row_u = row_y + ((width + 63) & ~63); - uint8* row_v = row_u + ((width + 63) & ~63) / 2; - YUY2ToUV422Row_SSE2(src_yuy2, row_u, row_v, width); - YUY2ToYRow_SSE2(src_yuy2, row_y, width); - I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width); - free_aligned_buffer_64(row_y); -} - -void YUY2ToARGBRow_Unaligned_SSSE3(const uint8* src_yuy2, - uint8* dst_argb, - int width) { - // Allocate a rows of yuv. - align_buffer_64(row_y, ((width + 63) & ~63) * 2); - uint8* row_u = row_y + ((width + 63) & ~63); - uint8* row_v = row_u + ((width + 63) & ~63) / 2; - YUY2ToUV422Row_Unaligned_SSE2(src_yuy2, row_u, row_v, width); - YUY2ToYRow_Unaligned_SSE2(src_yuy2, row_y, width); - I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width); - free_aligned_buffer_64(row_y); -} - -void UYVYToARGBRow_SSSE3(const uint8* src_uyvy, - uint8* dst_argb, - int width) { - // Allocate a rows of yuv. - align_buffer_64(row_y, ((width + 63) & ~63) * 2); - uint8* row_u = row_y + ((width + 63) & ~63); - uint8* row_v = row_u + ((width + 63) & ~63) / 2; - UYVYToUV422Row_SSE2(src_uyvy, row_u, row_v, width); - UYVYToYRow_SSE2(src_uyvy, row_y, width); - I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width); - free_aligned_buffer_64(row_y); -} - -void UYVYToARGBRow_Unaligned_SSSE3(const uint8* src_uyvy, - uint8* dst_argb, - int width) { - // Allocate a rows of yuv. - align_buffer_64(row_y, ((width + 63) & ~63) * 2); - uint8* row_u = row_y + ((width + 63) & ~63); - uint8* row_v = row_u + ((width + 63) & ~63) / 2; - UYVYToUV422Row_Unaligned_SSE2(src_uyvy, row_u, row_v, width); - UYVYToYRow_Unaligned_SSE2(src_uyvy, row_y, width); - I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width); - free_aligned_buffer_64(row_y); -} - -#endif // defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) -#endif // !defined(LIBYUV_DISABLE_X86) void ARGBPolynomialRow_C(const uint8* src_argb, - uint8* dst_argb, const float* poly, + uint8* dst_argb, + const float* poly, int width) { int i; for (i = 0; i < width; ++i) { @@ -2280,6 +2438,204 @@ void ARGBCopyYToAlphaRow_C(const uint8* src, uint8* dst, int width) { } } +// Maximum temporary width for wrappers to process at a time, in pixels. +#define MAXTWIDTH 2048 + +#if !(defined(_MSC_VER) && defined(_M_IX86)) && \ + defined(HAS_I422TORGB565ROW_SSSE3) +// row_win.cc has asm version, but GCC uses 2 step wrapper. +void I422ToRGB565Row_SSSE3(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width) { + SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToRGB565Row_SSE2(row, dst_rgb565, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_rgb565 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TOARGB1555ROW_SSSE3) +void I422ToARGB1555Row_SSSE3(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToARGB1555Row_SSE2(row, dst_argb1555, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_argb1555 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TOARGB4444ROW_SSSE3) +void I422ToARGB4444Row_SSSE3(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToARGB4444Row_SSE2(row, dst_argb4444, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_argb4444 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_NV12TORGB565ROW_SSSE3) +void NV12ToRGB565Row_SSSE3(const uint8* src_y, + const uint8* src_uv, + uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + NV12ToARGBRow_SSSE3(src_y, src_uv, row, yuvconstants, twidth); + ARGBToRGB565Row_SSE2(row, dst_rgb565, twidth); + src_y += twidth; + src_uv += twidth; + dst_rgb565 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TORGB565ROW_AVX2) +void I422ToRGB565Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width) { + SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_AVX2(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToRGB565Row_AVX2(row, dst_rgb565, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_rgb565 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TOARGB1555ROW_AVX2) +void I422ToARGB1555Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_AVX2(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToARGB1555Row_AVX2(row, dst_argb1555, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_argb1555 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TOARGB4444ROW_AVX2) +void I422ToARGB4444Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_AVX2(src_y, src_u, src_v, row, yuvconstants, twidth); + ARGBToARGB4444Row_AVX2(row, dst_argb4444, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_argb4444 += twidth * 2; + width -= twidth; + } +} +#endif + +#if defined(HAS_I422TORGB24ROW_AVX2) +void I422ToRGB24Row_AVX2(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + I422ToARGBRow_AVX2(src_y, src_u, src_v, row, yuvconstants, twidth); + // TODO(fbarchard): ARGBToRGB24Row_AVX2 + ARGBToRGB24Row_SSSE3(row, dst_rgb24, twidth); + src_y += twidth; + src_u += twidth / 2; + src_v += twidth / 2; + dst_rgb24 += twidth * 3; + width -= twidth; + } +} +#endif + +#if defined(HAS_NV12TORGB565ROW_AVX2) +void NV12ToRGB565Row_AVX2(const uint8* src_y, + const uint8* src_uv, + uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width) { + // Row buffer for intermediate ARGB pixels. + SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); + while (width > 0) { + int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; + NV12ToARGBRow_AVX2(src_y, src_uv, row, yuvconstants, twidth); + ARGBToRGB565Row_AVX2(row, dst_rgb565, twidth); + src_y += twidth; + src_uv += twidth; + dst_rgb565 += twidth * 2; + width -= twidth; + } +} +#endif + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/TMessagesProj/jni/libyuv/source/row_mips.cc b/TMessagesProj/jni/libyuv/source/row_mips.cc index da7183bc..d12cf6ab 100644 --- a/TMessagesProj/jni/libyuv/source/row_mips.cc +++ b/TMessagesProj/jni/libyuv/source/row_mips.cc @@ -389,7 +389,6 @@ void SplitUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, "blez $t4, 2f \n" " andi %[width], %[width], 0xf \n" // residual - ".p2align 2 \n" "1: \n" "addiu $t4, $t4, -1 \n" "lw $t0, 0(%[src_uv]) \n" // V1 | U1 | V0 | U0 @@ -447,89 +446,6 @@ void SplitUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, ); } -void SplitUVRow_Unaligned_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, - uint8* dst_v, int width) { - __asm__ __volatile__ ( - ".set push \n" - ".set noreorder \n" - "srl $t4, %[width], 4 \n" // multiplies of 16 - "blez $t4, 2f \n" - " andi %[width], %[width], 0xf \n" // residual - - ".p2align 2 \n" - "1: \n" - "addiu $t4, $t4, -1 \n" - "lwr $t0, 0(%[src_uv]) \n" - "lwl $t0, 3(%[src_uv]) \n" // V1 | U1 | V0 | U0 - "lwr $t1, 4(%[src_uv]) \n" - "lwl $t1, 7(%[src_uv]) \n" // V3 | U3 | V2 | U2 - "lwr $t2, 8(%[src_uv]) \n" - "lwl $t2, 11(%[src_uv]) \n" // V5 | U5 | V4 | U4 - "lwr $t3, 12(%[src_uv]) \n" - "lwl $t3, 15(%[src_uv]) \n" // V7 | U7 | V6 | U6 - "lwr $t5, 16(%[src_uv]) \n" - "lwl $t5, 19(%[src_uv]) \n" // V9 | U9 | V8 | U8 - "lwr $t6, 20(%[src_uv]) \n" - "lwl $t6, 23(%[src_uv]) \n" // V11 | U11 | V10 | U10 - "lwr $t7, 24(%[src_uv]) \n" - "lwl $t7, 27(%[src_uv]) \n" // V13 | U13 | V12 | U12 - "lwr $t8, 28(%[src_uv]) \n" - "lwl $t8, 31(%[src_uv]) \n" // V15 | U15 | V14 | U14 - "precrq.qb.ph $t9, $t1, $t0 \n" // V3 | V2 | V1 | V0 - "precr.qb.ph $t0, $t1, $t0 \n" // U3 | U2 | U1 | U0 - "precrq.qb.ph $t1, $t3, $t2 \n" // V7 | V6 | V5 | V4 - "precr.qb.ph $t2, $t3, $t2 \n" // U7 | U6 | U5 | U4 - "precrq.qb.ph $t3, $t6, $t5 \n" // V11 | V10 | V9 | V8 - "precr.qb.ph $t5, $t6, $t5 \n" // U11 | U10 | U9 | U8 - "precrq.qb.ph $t6, $t8, $t7 \n" // V15 | V14 | V13 | V12 - "precr.qb.ph $t7, $t8, $t7 \n" // U15 | U14 | U13 | U12 - "addiu %[src_uv], %[src_uv], 32 \n" - "swr $t9, 0(%[dst_v]) \n" - "swl $t9, 3(%[dst_v]) \n" - "swr $t0, 0(%[dst_u]) \n" - "swl $t0, 3(%[dst_u]) \n" - "swr $t1, 4(%[dst_v]) \n" - "swl $t1, 7(%[dst_v]) \n" - "swr $t2, 4(%[dst_u]) \n" - "swl $t2, 7(%[dst_u]) \n" - "swr $t3, 8(%[dst_v]) \n" - "swl $t3, 11(%[dst_v]) \n" - "swr $t5, 8(%[dst_u]) \n" - "swl $t5, 11(%[dst_u]) \n" - "swr $t6, 12(%[dst_v]) \n" - "swl $t6, 15(%[dst_v]) \n" - "swr $t7, 12(%[dst_u]) \n" - "swl $t7, 15(%[dst_u]) \n" - "addiu %[dst_u], %[dst_u], 16 \n" - "bgtz $t4, 1b \n" - " addiu %[dst_v], %[dst_v], 16 \n" - - "beqz %[width], 3f \n" - " nop \n" - - "2: \n" - "lbu $t0, 0(%[src_uv]) \n" - "lbu $t1, 1(%[src_uv]) \n" - "addiu %[src_uv], %[src_uv], 2 \n" - "addiu %[width], %[width], -1 \n" - "sb $t0, 0(%[dst_u]) \n" - "sb $t1, 0(%[dst_v]) \n" - "addiu %[dst_u], %[dst_u], 1 \n" - "bgtz %[width], 2b \n" - " addiu %[dst_v], %[dst_v], 1 \n" - - "3: \n" - ".set pop \n" - : [src_uv] "+r" (src_uv), - [width] "+r" (width), - [dst_u] "+r" (dst_u), - [dst_v] "+r" (dst_v) - : - : "t0", "t1", "t2", "t3", - "t4", "t5", "t6", "t7", "t8", "t9" - ); -} - void MirrorRow_MIPS_DSPR2(const uint8* src, uint8* dst, int width) { __asm__ __volatile__ ( ".set push \n" @@ -540,7 +456,6 @@ void MirrorRow_MIPS_DSPR2(const uint8* src, uint8* dst, int width) { "blez $t4, 2f \n" " addu %[src], %[src], %[width] \n" // src += width - ".p2align 2 \n" "1: \n" "lw $t0, -16(%[src]) \n" // |3|2|1|0| "lw $t1, -12(%[src]) \n" // |7|6|5|4| @@ -595,7 +510,6 @@ void MirrorUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, "blez %[x], 2f \n" " addu %[src_uv], %[src_uv], $t4 \n" - ".p2align 2 \n" "1: \n" "lw $t0, -32(%[src_uv]) \n" // |3|2|1|0| "lw $t1, -28(%[src_uv]) \n" // |7|6|5|4| @@ -679,7 +593,7 @@ void MirrorUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, // t8 = | 0 | G1 | 0 | g1 | // t2 = | 0 | R0 | 0 | r0 | // t1 = | 0 | R1 | 0 | r1 | -#define I422ToTransientMipsRGB \ +#define YUVTORGB \ "lw $t0, 0(%[y_buf]) \n" \ "lhu $t1, 0(%[u_buf]) \n" \ "lhu $t2, 0(%[v_buf]) \n" \ @@ -738,10 +652,12 @@ void MirrorUVRow_MIPS_DSPR2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, "addu.ph $t2, $t2, $s5 \n" \ "addu.ph $t1, $t1, $s5 \n" +// TODO(fbarchard): accept yuv conversion constants. void I422ToARGBRow_MIPS_DSPR2(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb_buf, + const struct YuvConstants* yuvconstants, int width) { __asm__ __volatile__ ( ".set push \n" @@ -756,9 +672,8 @@ void I422ToARGBRow_MIPS_DSPR2(const uint8* y_buf, "lui $s6, 0xff00 \n" "ori $s6, 0xff00 \n" // |ff|00|ff|00|ff| - ".p2align 2 \n" "1: \n" - I422ToTransientMipsRGB + YUVTORGB // Arranging into argb format "precr.qb.ph $t4, $t8, $t4 \n" // |G1|g1|B1|b1| "precr.qb.ph $t5, $t9, $t5 \n" // |G0|g0|B0|b0| @@ -800,136 +715,10 @@ void I422ToARGBRow_MIPS_DSPR2(const uint8* y_buf, ); } -void I422ToABGRRow_MIPS_DSPR2(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) { - __asm__ __volatile__ ( - ".set push \n" - ".set noreorder \n" - "beqz %[width], 2f \n" - " repl.ph $s0, 74 \n" // |YG|YG| = |74|74| - "repl.ph $s1, -25 \n" // |UG|UG| = |-25|-25| - "repl.ph $s2, -52 \n" // |VG|VG| = |-52|-52| - "repl.ph $s3, 102 \n" // |VR|VR| = |102|102| - "repl.ph $s4, 16 \n" // |0|16|0|16| - "repl.ph $s5, 128 \n" // |128|128| - "lui $s6, 0xff00 \n" - "ori $s6, 0xff00 \n" // |ff|00|ff|00| - - ".p2align 2 \n" - "1: \n" - I422ToTransientMipsRGB -// Arranging into abgr format - "precr.qb.ph $t0, $t8, $t1 \n" // |G1|g1|R1|r1| - "precr.qb.ph $t3, $t9, $t2 \n" // |G0|g0|R0|r0| - "precrq.qb.ph $t8, $t0, $t3 \n" // |G1|R1|G0|R0| - "precr.qb.ph $t9, $t0, $t3 \n" // |g1|r1|g0|r0| - - "precr.qb.ph $t2, $t4, $t5 \n" // |B1|b1|B0|b0| - "addiu %[width], -4 \n" - "addiu %[y_buf], 4 \n" - "preceu.ph.qbla $t1, $t2 \n" // |0 |B1|0 |B0| - "preceu.ph.qbra $t2, $t2 \n" // |0 |b1|0 |b0| - "or $t1, $t1, $s6 \n" // |ff|B1|ff|B0| - "or $t2, $t2, $s6 \n" // |ff|b1|ff|b0| - "precrq.ph.w $t0, $t2, $t9 \n" // |ff|b1|g1|r1| - "precrq.ph.w $t3, $t1, $t8 \n" // |ff|B1|G1|R1| - "sll $t9, $t9, 16 \n" - "sll $t8, $t8, 16 \n" - "packrl.ph $t2, $t2, $t9 \n" // |ff|b0|g0|r0| - "packrl.ph $t1, $t1, $t8 \n" // |ff|B0|G0|R0| -// Store results. - "sw $t2, 0(%[rgb_buf]) \n" - "sw $t0, 4(%[rgb_buf]) \n" - "sw $t1, 8(%[rgb_buf]) \n" - "sw $t3, 12(%[rgb_buf]) \n" - "bnez %[width], 1b \n" - " addiu %[rgb_buf], 16 \n" - "2: \n" - ".set pop \n" - :[y_buf] "+r" (y_buf), - [u_buf] "+r" (u_buf), - [v_buf] "+r" (v_buf), - [width] "+r" (width), - [rgb_buf] "+r" (rgb_buf) - : - : "t0", "t1", "t2", "t3", "t4", "t5", - "t6", "t7", "t8", "t9", - "s0", "s1", "s2", "s3", - "s4", "s5", "s6" - ); -} - -void I422ToBGRARow_MIPS_DSPR2(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* rgb_buf, - int width) { - __asm__ __volatile__ ( - ".set push \n" - ".set noreorder \n" - "beqz %[width], 2f \n" - " repl.ph $s0, 74 \n" // |YG|YG| = |74 |74 | - "repl.ph $s1, -25 \n" // |UG|UG| = |-25|-25| - "repl.ph $s2, -52 \n" // |VG|VG| = |-52|-52| - "repl.ph $s3, 102 \n" // |VR|VR| = |102|102| - "repl.ph $s4, 16 \n" // |0|16|0|16| - "repl.ph $s5, 128 \n" // |128|128| - "lui $s6, 0xff \n" - "ori $s6, 0xff \n" // |00|ff|00|ff| - - ".p2align 2 \n" - "1: \n" - I422ToTransientMipsRGB - // Arranging into bgra format - "precr.qb.ph $t4, $t4, $t8 \n" // |B1|b1|G1|g1| - "precr.qb.ph $t5, $t5, $t9 \n" // |B0|b0|G0|g0| - "precrq.qb.ph $t8, $t4, $t5 \n" // |B1|G1|B0|G0| - "precr.qb.ph $t9, $t4, $t5 \n" // |b1|g1|b0|g0| - - "precr.qb.ph $t2, $t1, $t2 \n" // |R1|r1|R0|r0| - "addiu %[width], -4 \n" - "addiu %[y_buf], 4 \n" - "preceu.ph.qbla $t1, $t2 \n" // |0 |R1|0 |R0| - "preceu.ph.qbra $t2, $t2 \n" // |0 |r1|0 |r0| - "sll $t1, $t1, 8 \n" // |R1|0 |R0|0 | - "sll $t2, $t2, 8 \n" // |r1|0 |r0|0 | - "or $t1, $t1, $s6 \n" // |R1|ff|R0|ff| - "or $t2, $t2, $s6 \n" // |r1|ff|r0|ff| - "precrq.ph.w $t0, $t9, $t2 \n" // |b1|g1|r1|ff| - "precrq.ph.w $t3, $t8, $t1 \n" // |B1|G1|R1|ff| - "sll $t1, $t1, 16 \n" - "sll $t2, $t2, 16 \n" - "packrl.ph $t2, $t9, $t2 \n" // |b0|g0|r0|ff| - "packrl.ph $t1, $t8, $t1 \n" // |B0|G0|R0|ff| -// Store results. - "sw $t2, 0(%[rgb_buf]) \n" - "sw $t0, 4(%[rgb_buf]) \n" - "sw $t1, 8(%[rgb_buf]) \n" - "sw $t3, 12(%[rgb_buf]) \n" - "bnez %[width], 1b \n" - " addiu %[rgb_buf], 16 \n" - "2: \n" - ".set pop \n" - :[y_buf] "+r" (y_buf), - [u_buf] "+r" (u_buf), - [v_buf] "+r" (v_buf), - [width] "+r" (width), - [rgb_buf] "+r" (rgb_buf) - : - : "t0", "t1", "t2", "t3", "t4", "t5", - "t6", "t7", "t8", "t9", - "s0", "s1", "s2", "s3", - "s4", "s5", "s6" - ); -} - // Bilinear filter 8x2 -> 8x1 -void InterpolateRows_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { +void InterpolateRow_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) { int y0_fraction = 256 - source_y_fraction; const uint8* src_ptr1 = src_ptr + src_stride; @@ -940,7 +729,6 @@ void InterpolateRows_MIPS_DSPR2(uint8* dst_ptr, const uint8* src_ptr, "replv.ph $t0, %[y0_fraction] \n" "replv.ph $t1, %[source_y_fraction] \n" - ".p2align 2 \n" "1: \n" "lw $t2, 0(%[src_ptr]) \n" "lw $t3, 0(%[src_ptr1]) \n" diff --git a/TMessagesProj/jni/libyuv/source/row_neon.cc b/TMessagesProj/jni/libyuv/source/row_neon.cc index 1392cf5f..5b4ff3b5 100644 --- a/TMessagesProj/jni/libyuv/source/row_neon.cc +++ b/TMessagesProj/jni/libyuv/source/row_neon.cc @@ -16,7 +16,8 @@ extern "C" { #endif // This module is for GCC Neon -#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) +#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \ + !defined(__aarch64__) // Read 8 Y, 4 U and 4 V from 422 #define READYUV422 \ @@ -92,56 +93,60 @@ extern "C" { "vuzp.u8 d2, d3 \n" \ "vtrn.u32 d2, d3 \n" -#define YUV422TORGB \ - "veor.u8 d2, d26 \n"/*subtract 128 from u and v*/\ - "vmull.s8 q8, d2, d24 \n"/* u/v B/R component */\ - "vmull.s8 q9, d2, d25 \n"/* u/v G component */\ - "vmov.u8 d1, #0 \n"/* split odd/even y apart */\ - "vtrn.u8 d0, d1 \n" \ - "vsub.s16 q0, q0, q15 \n"/* offset y */\ - "vmul.s16 q0, q0, q14 \n" \ - "vadd.s16 d18, d19 \n" \ - "vqadd.s16 d20, d0, d16 \n" /* B */ \ - "vqadd.s16 d21, d1, d16 \n" \ - "vqadd.s16 d22, d0, d17 \n" /* R */ \ - "vqadd.s16 d23, d1, d17 \n" \ - "vqadd.s16 d16, d0, d18 \n" /* G */ \ - "vqadd.s16 d17, d1, d18 \n" \ - "vqshrun.s16 d0, q10, #6 \n" /* B */ \ - "vqshrun.s16 d1, q11, #6 \n" /* G */ \ - "vqshrun.s16 d2, q8, #6 \n" /* R */ \ - "vmovl.u8 q10, d0 \n"/* set up for reinterleave*/\ - "vmovl.u8 q11, d1 \n" \ - "vmovl.u8 q8, d2 \n" \ - "vtrn.u8 d20, d21 \n" \ - "vtrn.u8 d22, d23 \n" \ - "vtrn.u8 d16, d17 \n" \ - "vmov.u8 d21, d16 \n" +#define YUVTORGB_SETUP \ + MEMACCESS([kUVToRB]) \ + "vld1.8 {d24}, [%[kUVToRB]] \n" \ + MEMACCESS([kUVToG]) \ + "vld1.8 {d25}, [%[kUVToG]] \n" \ + MEMACCESS([kUVBiasBGR]) \ + "vld1.16 {d26[], d27[]}, [%[kUVBiasBGR]]! \n" \ + MEMACCESS([kUVBiasBGR]) \ + "vld1.16 {d8[], d9[]}, [%[kUVBiasBGR]]! \n" \ + MEMACCESS([kUVBiasBGR]) \ + "vld1.16 {d28[], d29[]}, [%[kUVBiasBGR]] \n" \ + MEMACCESS([kYToRgb]) \ + "vld1.32 {d30[], d31[]}, [%[kYToRgb]] \n" -static vec8 kUVToRB = { 127, 127, 127, 127, 102, 102, 102, 102, - 0, 0, 0, 0, 0, 0, 0, 0 }; -static vec8 kUVToG = { -25, -25, -25, -25, -52, -52, -52, -52, - 0, 0, 0, 0, 0, 0, 0, 0 }; +#define YUVTORGB \ + "vmull.u8 q8, d2, d24 \n" /* u/v B/R component */\ + "vmull.u8 q9, d2, d25 \n" /* u/v G component */\ + "vmovl.u8 q0, d0 \n" /* Y */\ + "vmovl.s16 q10, d1 \n" \ + "vmovl.s16 q0, d0 \n" \ + "vmul.s32 q10, q10, q15 \n" \ + "vmul.s32 q0, q0, q15 \n" \ + "vqshrun.s32 d0, q0, #16 \n" \ + "vqshrun.s32 d1, q10, #16 \n" /* Y */\ + "vadd.s16 d18, d19 \n" \ + "vshll.u16 q1, d16, #16 \n" /* Replicate u * UB */\ + "vshll.u16 q10, d17, #16 \n" /* Replicate v * VR */\ + "vshll.u16 q3, d18, #16 \n" /* Replicate (v*VG + u*UG)*/\ + "vaddw.u16 q1, q1, d16 \n" \ + "vaddw.u16 q10, q10, d17 \n" \ + "vaddw.u16 q3, q3, d18 \n" \ + "vqadd.s16 q8, q0, q13 \n" /* B */ \ + "vqadd.s16 q9, q0, q14 \n" /* R */ \ + "vqadd.s16 q0, q0, q4 \n" /* G */ \ + "vqadd.s16 q8, q8, q1 \n" /* B */ \ + "vqadd.s16 q9, q9, q10 \n" /* R */ \ + "vqsub.s16 q0, q0, q3 \n" /* G */ \ + "vqshrun.s16 d20, q8, #6 \n" /* B */ \ + "vqshrun.s16 d22, q9, #6 \n" /* R */ \ + "vqshrun.s16 d21, q0, #6 \n" /* G */ void I444ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READYUV444 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(3) "vst4.8 {d20, d21, d22, d23}, [%3]! \n" "bgt 1b \n" @@ -150,9 +155,11 @@ void I444ToARGBRow_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -161,21 +168,15 @@ void I422ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(3) "vst4.8 {d20, d21, d22, d23}, [%3]! \n" "bgt 1b \n" @@ -184,9 +185,44 @@ void I422ToARGBRow_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); +} + +void I422AlphaToARGBRow_NEON(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + const uint8* src_a, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + asm volatile ( + YUVTORGB_SETUP + "1: \n" + READYUV422 + YUVTORGB + "subs %5, %5, #8 \n" + MEMACCESS(3) + "vld1.8 {d23}, [%3]! \n" + MEMACCESS(4) + "vst4.8 {d20, d21, d22, d23}, [%4]! \n" + "bgt 1b \n" + : "+r"(src_y), // %0 + "+r"(src_u), // %1 + "+r"(src_v), // %2 + "+r"(src_a), // %3 + "+r"(dst_argb), // %4 + "+r"(width) // %5 + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -195,21 +231,15 @@ void I411ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READYUV411 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(3) "vst4.8 {d20, d21, d22, d23}, [%3]! \n" "bgt 1b \n" @@ -218,79 +248,11 @@ void I411ToARGBRow_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} - -void I422ToBGRARow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - "vmov.u8 d19, #255 \n" - MEMACCESS(3) - "vst4.8 {d19, d20, d21, d22}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_bgra), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} - -void I422ToABGRRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - "vmov.u8 d23, #255 \n" - MEMACCESS(3) - "vst4.8 {d20, d21, d22, d23}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_abgr), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -299,21 +261,15 @@ void I422ToRGBARow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" - "vmov.u8 d19, #255 \n" + "vmov.u8 d19, #255 \n" // d19 modified by YUVTORGB MEMACCESS(3) "vst4.8 {d19, d20, d21, d22}, [%3]! \n" "bgt 1b \n" @@ -322,9 +278,11 @@ void I422ToRGBARow_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_rgba), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -333,19 +291,13 @@ void I422ToRGB24Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" MEMACCESS(3) "vst3.8 {d20, d21, d22}, [%3]! \n" @@ -355,43 +307,11 @@ void I422ToRGB24Row_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_rgb24), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} - -void I422ToRAWRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_raw, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - MEMACCESS(3) - "vst3.8 {d20, d21, d22}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_raw), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -412,19 +332,13 @@ void I422ToRGB565Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" ARGBTORGB565 MEMACCESS(3) @@ -435,9 +349,11 @@ void I422ToRGB565Row_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_rgb565), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -461,19 +377,13 @@ void I422ToARGB1555Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" "vmov.u8 d23, #255 \n" ARGBTOARGB1555 @@ -485,9 +395,11 @@ void I422ToARGB1555Row_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_argb1555), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -505,20 +417,14 @@ void I422ToARGB4444Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" + YUVTORGB_SETUP "vmov.u8 d4, #0x0f \n" // bits to clear with vbic. - ".p2align 2 \n" "1: \n" READYUV422 - YUV422TORGB + YUVTORGB "subs %4, %4, #8 \n" "vmov.u8 d23, #255 \n" ARGBTOARGB4444 @@ -530,39 +436,11 @@ void I422ToARGB4444Row_NEON(const uint8* src_y, "+r"(src_v), // %2 "+r"(dst_argb4444), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} - -void YToARGBRow_NEON(const uint8* src_y, - uint8* dst_argb, - int width) { - asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV400 - YUV422TORGB - "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" - MEMACCESS(1) - "vst4.8 {d20, d21, d22, d23}, [%1]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -571,7 +449,31 @@ void I400ToARGBRow_NEON(const uint8* src_y, uint8* dst_argb, int width) { asm volatile ( - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" + "1: \n" + READYUV400 + YUVTORGB + "subs %2, %2, #8 \n" + MEMACCESS(1) + "vst4.8 {d20, d21, d22, d23}, [%1]! \n" + "bgt 1b \n" + : "+r"(src_y), // %0 + "+r"(dst_argb), // %1 + "+r"(width) // %2 + : [kUVToRB]"r"(&kYuvI601Constants.kUVToRB), + [kUVToG]"r"(&kYuvI601Constants.kUVToG), + [kUVBiasBGR]"r"(&kYuvI601Constants.kUVBiasBGR), + [kYToRgb]"r"(&kYuvI601Constants.kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); +} + +void J400ToARGBRow_NEON(const uint8* src_y, + uint8* dst_argb, + int width) { + asm volatile ( "vmov.u8 d23, #255 \n" "1: \n" MEMACCESS(0) @@ -593,21 +495,15 @@ void I400ToARGBRow_NEON(const uint8* src_y, void NV12ToARGBRow_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READNV12 - YUV422TORGB + YUVTORGB "subs %3, %3, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(2) "vst4.8 {d20, d21, d22, d23}, [%2]! \n" "bgt 1b \n" @@ -615,41 +511,39 @@ void NV12ToARGBRow_NEON(const uint8* src_y, "+r"(src_uv), // %1 "+r"(dst_argb), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } void NV21ToARGBRow_NEON(const uint8* src_y, - const uint8* src_uv, + const uint8* src_vu, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READNV21 - YUV422TORGB + YUVTORGB "subs %3, %3, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(2) "vst4.8 {d20, d21, d22, d23}, [%2]! \n" "bgt 1b \n" : "+r"(src_y), // %0 - "+r"(src_uv), // %1 + "+r"(src_vu), // %1 "+r"(dst_argb), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -657,19 +551,13 @@ void NV21ToARGBRow_NEON(const uint8* src_y, void NV12ToRGB565Row_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READNV12 - YUV422TORGB + YUVTORGB "subs %3, %3, #8 \n" ARGBTORGB565 MEMACCESS(2) @@ -679,101 +567,63 @@ void NV12ToRGB565Row_NEON(const uint8* src_y, "+r"(src_uv), // %1 "+r"(dst_rgb565), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} - -void NV21ToRGB565Row_NEON(const uint8* src_y, - const uint8* src_uv, - uint8* dst_rgb565, - int width) { - asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READNV21 - YUV422TORGB - "subs %3, %3, #8 \n" - ARGBTORGB565 - MEMACCESS(2) - "vst1.8 {q0}, [%2]! \n" // store 8 pixels RGB565. - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_uv), // %1 - "+r"(dst_rgb565), // %2 - "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } void YUY2ToARGBRow_NEON(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READYUY2 - YUV422TORGB + YUVTORGB "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(1) "vst4.8 {d20, d21, d22, d23}, [%1]! \n" "bgt 1b \n" : "+r"(src_yuy2), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } void UYVYToARGBRow_NEON(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "vmov.u8 d23, #255 \n" "1: \n" READUYVY - YUV422TORGB + YUVTORGB "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" MEMACCESS(1) "vst4.8 {d20, d21, d22, d23}, [%1]! \n" "bgt 1b \n" : "+r"(src_uyvy), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -782,7 +632,6 @@ void UYVYToARGBRow_NEON(const uint8* src_uyvy, void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {q0, q1}, [%0]! \n" // load 16 pairs of UV @@ -805,7 +654,6 @@ void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, void MergeUVRow_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load U @@ -828,7 +676,6 @@ void MergeUVRow_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, // Copy multiple of 32. vld4.8 allow unaligned and is fastest on a15. void CopyRow_NEON(const uint8* src, uint8* dst, int count) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0, d1, d2, d3}, [%0]! \n" // load 32 @@ -844,12 +691,28 @@ void CopyRow_NEON(const uint8* src, uint8* dst, int count) { ); } -// SetRow8 writes 'count' bytes using a 32 bit value repeated. -void SetRow_NEON(uint8* dst, uint32 v32, int count) { +// SetRow writes 'count' bytes using an 8 bit value repeated. +void SetRow_NEON(uint8* dst, uint8 v8, int count) { + asm volatile ( + "vdup.8 q0, %2 \n" // duplicate 16 bytes + "1: \n" + "subs %1, %1, #16 \n" // 16 bytes per loop + MEMACCESS(0) + "vst1.8 {q0}, [%0]! \n" // store + "bgt 1b \n" + : "+r"(dst), // %0 + "+r"(count) // %1 + : "r"(v8) // %2 + : "cc", "memory", "q0" + ); +} + +// ARGBSetRow writes 'count' pixels using an 32 bit value repeated. +void ARGBSetRow_NEON(uint8* dst, uint32 v32, int count) { asm volatile ( "vdup.u32 q0, %2 \n" // duplicate 4 ints - "1: \n" - "subs %1, %1, #16 \n" // 16 bytes per loop + "1: \n" + "subs %1, %1, #4 \n" // 4 pixels per loop MEMACCESS(0) "vst1.8 {q0}, [%0]! \n" // store "bgt 1b \n" @@ -860,16 +723,6 @@ void SetRow_NEON(uint8* dst, uint32 v32, int count) { ); } -// TODO(fbarchard): Make fully assembler -// SetRow32 writes 'count' words using a 32 bit value repeated. -void ARGBSetRows_NEON(uint8* dst, uint32 v32, int width, - int dst_stride, int height) { - for (int y = 0; y < height; ++y) { - SetRow_NEON(dst, v32, width << 2); - dst += dst_stride; - } -} - void MirrorRow_NEON(const uint8* src, uint8* dst, int width) { asm volatile ( // Start at end of source row. @@ -877,7 +730,6 @@ void MirrorRow_NEON(const uint8* src, uint8* dst, int width) { "add %0, %0, %2 \n" "sub %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0], r3 \n" // src -= 16 @@ -904,7 +756,6 @@ void MirrorUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, "add %0, %0, %3, lsl #1 \n" "sub %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {d0, d1}, [%0], r12 \n" // src -= 16 @@ -931,7 +782,6 @@ void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width) { "add %0, %0, %2, lsl #2 \n" "sub %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0], r3 \n" // src -= 16 @@ -950,10 +800,9 @@ void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width) { ); } -void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix) { +void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int width) { asm volatile ( "vmov.u8 d4, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d1, d2, d3}, [%0]! \n" // load 8 pixels of RGB24. @@ -963,16 +812,15 @@ void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix) { "bgt 1b \n" : "+r"(src_rgb24), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d1", "d2", "d3", "d4" // Clobber List ); } -void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int pix) { +void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int width) { asm volatile ( "vmov.u8 d4, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d1, d2, d3}, [%0]! \n" // load 8 pixels of RAW. @@ -983,12 +831,30 @@ void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int pix) { "bgt 1b \n" : "+r"(src_raw), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d1", "d2", "d3", "d4" // Clobber List ); } +void RAWToRGB24Row_NEON(const uint8* src_raw, uint8* dst_rgb24, int width) { + asm volatile ( + "1: \n" + MEMACCESS(0) + "vld3.8 {d1, d2, d3}, [%0]! \n" // load 8 pixels of RAW. + "subs %2, %2, #8 \n" // 8 processed per loop. + "vswp.u8 d1, d3 \n" // swap R, B + MEMACCESS(1) + "vst3.8 {d1, d2, d3}, [%1]! \n" // store 8 pixels of RGB24. + "bgt 1b \n" + : "+r"(src_raw), // %0 + "+r"(dst_rgb24), // %1 + "+r"(width) // %2 + : + : "cc", "memory", "d1", "d2", "d3" // Clobber List + ); +} + #define RGB565TOARGB \ "vshrn.u16 d6, q0, #5 \n" /* G xxGGGGGG */ \ "vuzp.u8 d0, d1 \n" /* d0 xxxBBBBB RRRRRxxx */ \ @@ -1001,10 +867,9 @@ void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int pix) { "vorr.u8 d2, d1, d5 \n" /* R */ \ "vorr.u8 d1, d4, d6 \n" /* G */ -void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int pix) { +void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int width) { asm volatile ( "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. @@ -1015,7 +880,7 @@ void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int pix) { "bgt 1b \n" : "+r"(src_rgb565), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q3" // Clobber List ); @@ -1049,10 +914,9 @@ void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int pix) { "vorr.u8 d1, d4, d6 \n" /* G */ void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, - int pix) { + int width) { asm volatile ( "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. @@ -1063,7 +927,7 @@ void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, "bgt 1b \n" : "+r"(src_argb1555), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q3" // Clobber List ); @@ -1080,10 +944,9 @@ void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, "vswp.u8 d1, d2 \n" /* B,R,G,A -> B,G,R,A */ void ARGB4444ToARGBRow_NEON(const uint8* src_argb4444, uint8* dst_argb, - int pix) { + int width) { asm volatile ( "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. @@ -1094,15 +957,14 @@ void ARGB4444ToARGBRow_NEON(const uint8* src_argb4444, uint8* dst_argb, "bgt 1b \n" : "+r"(src_argb4444), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2" // Clobber List ); } -void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int pix) { +void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d1, d2, d3, d4}, [%0]! \n" // load 8 pixels of ARGB. @@ -1112,15 +974,14 @@ void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int pix) { "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_rgb24), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d1", "d2", "d3", "d4" // Clobber List ); } -void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int pix) { +void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d1, d2, d3, d4}, [%0]! \n" // load 8 pixels of ARGB. @@ -1131,15 +992,14 @@ void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int pix) { "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_raw), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d1", "d2", "d3", "d4" // Clobber List ); } -void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int pix) { +void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {q0, q1}, [%0]! \n" // load 16 pixels of YUY2. @@ -1149,15 +1009,14 @@ void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_yuy2), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1" // Clobber List ); } -void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int pix) { +void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {q0, q1}, [%0]! \n" // load 16 pixels of UYVY. @@ -1167,16 +1026,15 @@ void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_uyvy), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1" // Clobber List ); } void YUY2ToUV422Row_NEON(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 16 pixels of YUY2. @@ -1189,16 +1047,15 @@ void YUY2ToUV422Row_NEON(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v, : "+r"(src_yuy2), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "d0", "d1", "d2", "d3" // Clobber List ); } void UYVYToUV422Row_NEON(const uint8* src_uyvy, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 16 pixels of UYVY. @@ -1211,17 +1068,16 @@ void UYVYToUV422Row_NEON(const uint8* src_uyvy, uint8* dst_u, uint8* dst_v, : "+r"(src_uyvy), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "d0", "d1", "d2", "d3" // Clobber List ); } void YUY2ToUVRow_NEON(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // stride + src_yuy2 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 16 pixels of YUY2. @@ -1239,17 +1095,16 @@ void YUY2ToUVRow_NEON(const uint8* src_yuy2, int stride_yuy2, "+r"(stride_yuy2), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" // Clobber List ); } void UYVYToUVRow_NEON(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // stride + src_uyvy - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 16 pixels of UYVY. @@ -1267,81 +1122,15 @@ void UYVYToUVRow_NEON(const uint8* src_uyvy, int stride_uyvy, "+r"(stride_uyvy), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" // Clobber List ); } -void HalfRow_NEON(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { - asm volatile ( - // change the stride to row 2 pointer - "add %1, %0 \n" - "1: \n" - MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load row 1 16 pixels. - "subs %3, %3, #16 \n" // 16 processed per loop - MEMACCESS(1) - "vld1.8 {q1}, [%1]! \n" // load row 2 16 pixels. - "vrhadd.u8 q0, q1 \n" // average row 1 and 2 - MEMACCESS(2) - "vst1.8 {q0}, [%2]! \n" - "bgt 1b \n" - : "+r"(src_uv), // %0 - "+r"(src_uv_stride), // %1 - "+r"(dst_uv), // %2 - "+r"(pix) // %3 - : - : "cc", "memory", "q0", "q1" // Clobber List - ); -} - -// Select 2 channels from ARGB on alternating pixels. e.g. BGBGBGBG -void ARGBToBayerRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - asm volatile ( - "vmov.u32 d6[0], %3 \n" // selector - "1: \n" - MEMACCESS(0) - "vld1.8 {q0, q1}, [%0]! \n" // load row 8 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop - "vtbl.8 d4, {d0, d1}, d6 \n" // look up 4 pixels - "vtbl.8 d5, {d2, d3}, d6 \n" // look up 4 pixels - "vtrn.u32 d4, d5 \n" // combine 8 pixels - MEMACCESS(1) - "vst1.8 {d4}, [%1]! \n" // store 8. - "bgt 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : "r"(selector) // %3 - : "cc", "memory", "q0", "q1", "q2", "q3" // Clobber List - ); -} - -// Select G channels from ARGB. e.g. GGGGGGGG -void ARGBToBayerGGRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 /*selector*/, int pix) { - asm volatile ( - "1: \n" - MEMACCESS(0) - "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load row 8 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop - MEMACCESS(1) - "vst1.8 {d1}, [%1]! \n" // store 8 G's. - "bgt 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : - : "cc", "memory", "q0", "q1" // Clobber List - ); -} - // For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. void ARGBShuffleRow_NEON(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { asm volatile ( MEMACCESS(3) "vld1.8 {q2}, [%3] \n" // shuffler @@ -1356,7 +1145,7 @@ void ARGBShuffleRow_NEON(const uint8* src_argb, uint8* dst_argb, "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : "r"(shuffler) // %3 : "cc", "memory", "q0", "q1", "q2" // Clobber List ); @@ -1367,7 +1156,6 @@ void I422ToYUY2Row_NEON(const uint8* src_y, const uint8* src_v, uint8* dst_yuy2, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {d0, d2}, [%0]! \n" // load 16 Ys @@ -1394,7 +1182,6 @@ void I422ToUYVYRow_NEON(const uint8* src_y, const uint8* src_v, uint8* dst_uyvy, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld2.8 {d1, d3}, [%0]! \n" // load 16 Ys @@ -1416,9 +1203,8 @@ void I422ToUYVYRow_NEON(const uint8* src_y, ); } -void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb565, int pix) { +void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb565, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. @@ -1429,16 +1215,38 @@ void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb565, int pix) { "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_rgb565), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q8", "q9", "q10", "q11" ); } -void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_argb1555, - int pix) { +void ARGBToRGB565DitherRow_NEON(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) { + asm volatile ( + "vdup.32 d2, %2 \n" // dither4 + "1: \n" + MEMACCESS(1) + "vld4.8 {d20, d21, d22, d23}, [%1]! \n" // load 8 pixels of ARGB. + "subs %3, %3, #8 \n" // 8 processed per loop. + "vqadd.u8 d20, d20, d2 \n" + "vqadd.u8 d21, d21, d2 \n" + "vqadd.u8 d22, d22, d2 \n" + ARGBTORGB565 + MEMACCESS(0) + "vst1.8 {q0}, [%0]! \n" // store 8 pixels RGB565. + "bgt 1b \n" + : "+r"(dst_rgb) // %0 + : "r"(src_argb), // %1 + "r"(dither4), // %2 + "r"(width) // %3 + : "cc", "memory", "q0", "q1", "q8", "q9", "q10", "q11" + ); +} + +void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_argb1555, + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. @@ -1449,17 +1257,16 @@ void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_argb1555, "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb1555), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q8", "q9", "q10", "q11" ); } void ARGBToARGB4444Row_NEON(const uint8* src_argb, uint8* dst_argb4444, - int pix) { + int width) { asm volatile ( "vmov.u8 d4, #0x0f \n" // bits to clear with vbic. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. @@ -1470,19 +1277,18 @@ void ARGBToARGB4444Row_NEON(const uint8* src_argb, uint8* dst_argb4444, "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb4444), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q8", "q9", "q10", "q11" ); } -void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { +void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -1497,18 +1303,17 @@ void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q12", "q13" ); } -void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { +void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d24, #15 \n" // B * 0.11400 coefficient "vmov.u8 d25, #75 \n" // G * 0.58700 coefficient "vmov.u8 d26, #38 \n" // R * 0.29900 coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -1522,7 +1327,7 @@ void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q12", "q13" ); @@ -1530,7 +1335,7 @@ void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { // 8x1 pixels. void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( "vmov.u8 d24, #112 \n" // UB / VR 0.875 coefficient "vmov.u8 d25, #74 \n" // UG -0.5781 coefficient @@ -1538,7 +1343,6 @@ void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "vmov.u8 d27, #18 \n" // VB -0.1406 coefficient "vmov.u8 d28, #94 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -1564,15 +1368,15 @@ void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q12", "q13", "q14", "q15" ); } -// 16x1 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x1 pixels -> 8x1. width is number of argb pixels. e.g. 16. void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient @@ -1580,7 +1384,6 @@ void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -1613,16 +1416,16 @@ void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -// 32x1 pixels -> 8x1. pix is number of argb pixels. e.g. 32. +// 32x1 pixels -> 8x1. width is number of argb pixels. e.g. 32. void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient @@ -1630,7 +1433,6 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -1677,14 +1479,14 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. #define RGBTOUV(QB, QG, QR) \ "vmul.s16 q8, " #QB ", q10 \n" /* B */ \ "vmls.s16 q8, " #QG ", q11 \n" /* G */ \ @@ -1699,7 +1501,7 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, // TODO(fbarchard): Consider vhadd vertical, then vpaddl horizontal, avoid shr. void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_argb "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -1708,7 +1510,6 @@ void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -1740,7 +1541,7 @@ void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, "+r"(src_stride_argb), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1749,7 +1550,7 @@ void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, // TODO(fbarchard): Subsample match C code. void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_argb "vmov.s16 q10, #127 / 2 \n" // UB / VR 0.500 coefficient @@ -1758,7 +1559,6 @@ void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, "vmov.s16 q13, #20 / 2 \n" // VB -0.08131 coefficient "vmov.s16 q14, #107 / 2 \n" // VG -0.41869 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -1790,7 +1590,7 @@ void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, "+r"(src_stride_argb), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1798,7 +1598,7 @@ void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, } void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_bgra "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -1807,7 +1607,6 @@ void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 BGRA pixels. @@ -1839,7 +1638,7 @@ void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, "+r"(src_stride_bgra), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1847,7 +1646,7 @@ void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, } void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_abgr "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -1856,7 +1655,6 @@ void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ABGR pixels. @@ -1888,7 +1686,7 @@ void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, "+r"(src_stride_abgr), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1896,7 +1694,7 @@ void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, } void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_rgba "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -1905,7 +1703,6 @@ void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 RGBA pixels. @@ -1937,7 +1734,7 @@ void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, "+r"(src_stride_rgba), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1945,7 +1742,7 @@ void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, } void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_rgb24 "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -1954,7 +1751,6 @@ void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d0, d2, d4}, [%0]! \n" // load 8 RGB24 pixels. @@ -1986,7 +1782,7 @@ void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, "+r"(src_stride_rgb24), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -1994,7 +1790,7 @@ void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, } void RAWToUVRow_NEON(const uint8* src_raw, int src_stride_raw, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_raw "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -2003,7 +1799,6 @@ void RAWToUVRow_NEON(const uint8* src_raw, int src_stride_raw, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d0, d2, d4}, [%0]! \n" // load 8 RAW pixels. @@ -2035,16 +1830,16 @@ void RAWToUVRow_NEON(const uint8* src_raw, int src_stride_raw, "+r"(src_stride_raw), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. void RGB565ToUVRow_NEON(const uint8* src_rgb565, int src_stride_rgb565, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_argb "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -2053,7 +1848,6 @@ void RGB565ToUVRow_NEON(const uint8* src_rgb565, int src_stride_rgb565, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. @@ -2105,16 +1899,16 @@ void RGB565ToUVRow_NEON(const uint8* src_rgb565, int src_stride_rgb565, "+r"(src_stride_rgb565), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. void ARGB1555ToUVRow_NEON(const uint8* src_argb1555, int src_stride_argb1555, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_argb "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -2123,7 +1917,6 @@ void ARGB1555ToUVRow_NEON(const uint8* src_argb1555, int src_stride_argb1555, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. @@ -2175,16 +1968,16 @@ void ARGB1555ToUVRow_NEON(const uint8* src_argb1555, int src_stride_argb1555, "+r"(src_stride_argb1555), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. void ARGB4444ToUVRow_NEON(const uint8* src_argb4444, int src_stride_argb4444, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { asm volatile ( "add %1, %0, %1 \n" // src_stride + src_argb "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient @@ -2193,7 +1986,6 @@ void ARGB4444ToUVRow_NEON(const uint8* src_argb4444, int src_stride_argb4444, "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. @@ -2245,20 +2037,19 @@ void ARGB4444ToUVRow_NEON(const uint8* src_argb4444, int src_stride_argb4444, "+r"(src_stride_argb4444), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } -void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int pix) { +void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. @@ -2274,19 +2065,18 @@ void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_rgb565), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" ); } -void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int pix) { +void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. @@ -2302,19 +2092,18 @@ void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_argb1555), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" ); } -void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int pix) { +void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. @@ -2330,19 +2119,18 @@ void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_argb4444), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" ); } -void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix) { +void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d4, #33 \n" // R * 0.2578 coefficient "vmov.u8 d5, #65 \n" // G * 0.5078 coefficient "vmov.u8 d6, #13 \n" // B * 0.1016 coefficient "vmov.u8 d7, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 pixels of BGRA. @@ -2357,19 +2145,18 @@ void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_bgra), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8" ); } -void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix) { +void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d4, #33 \n" // R * 0.2578 coefficient "vmov.u8 d5, #65 \n" // G * 0.5078 coefficient "vmov.u8 d6, #13 \n" // B * 0.1016 coefficient "vmov.u8 d7, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 pixels of ABGR. @@ -2384,19 +2171,18 @@ void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_abgr), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8" ); } -void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix) { +void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d4, #13 \n" // B * 0.1016 coefficient "vmov.u8 d5, #65 \n" // G * 0.5078 coefficient "vmov.u8 d6, #33 \n" // R * 0.2578 coefficient "vmov.u8 d7, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 pixels of RGBA. @@ -2411,19 +2197,18 @@ void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_rgba), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8" ); } -void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix) { +void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d4, #13 \n" // B * 0.1016 coefficient "vmov.u8 d5, #65 \n" // G * 0.5078 coefficient "vmov.u8 d6, #33 \n" // R * 0.2578 coefficient "vmov.u8 d7, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d0, d1, d2}, [%0]! \n" // load 8 pixels of RGB24. @@ -2438,19 +2223,18 @@ void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_rgb24), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8" ); } -void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix) { +void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int width) { asm volatile ( "vmov.u8 d4, #33 \n" // R * 0.2578 coefficient "vmov.u8 d5, #65 \n" // G * 0.5078 coefficient "vmov.u8 d6, #13 \n" // B * 0.1016 coefficient "vmov.u8 d7, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld3.8 {d0, d1, d2}, [%0]! \n" // load 8 pixels of RAW. @@ -2465,7 +2249,7 @@ void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix) { "bgt 1b \n" : "+r"(src_raw), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8" ); @@ -2475,16 +2259,13 @@ void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix) { void InterpolateRow_NEON(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) { + int y1_fraction = source_y_fraction; asm volatile ( "cmp %4, #0 \n" "beq 100f \n" "add %2, %1 \n" - "cmp %4, #64 \n" - "beq 75f \n" "cmp %4, #128 \n" "beq 50f \n" - "cmp %4, #192 \n" - "beq 25f \n" "vdup.8 d5, %4 \n" "rsb %4, #256 \n" @@ -2507,20 +2288,6 @@ void InterpolateRow_NEON(uint8* dst_ptr, "bgt 1b \n" "b 99f \n" - // Blend 25 / 75. - "25: \n" - MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" - MEMACCESS(2) - "vld1.8 {q1}, [%2]! \n" - "subs %3, %3, #16 \n" - "vrhadd.u8 q0, q1 \n" - "vrhadd.u8 q0, q1 \n" - MEMACCESS(0) - "vst1.8 {q0}, [%0]! \n" - "bgt 25b \n" - "b 99f \n" - // Blend 50 / 50. "50: \n" MEMACCESS(1) @@ -2534,20 +2301,6 @@ void InterpolateRow_NEON(uint8* dst_ptr, "bgt 50b \n" "b 99f \n" - // Blend 75 / 25. - "75: \n" - MEMACCESS(1) - "vld1.8 {q1}, [%1]! \n" - MEMACCESS(2) - "vld1.8 {q0}, [%2]! \n" - "subs %3, %3, #16 \n" - "vrhadd.u8 q0, q1 \n" - "vrhadd.u8 q0, q1 \n" - MEMACCESS(0) - "vst1.8 {q0}, [%0]! \n" - "bgt 75b \n" - "b 99f \n" - // Blend 100 / 0 - Copy row unchanged. "100: \n" MEMACCESS(1) @@ -2562,7 +2315,7 @@ void InterpolateRow_NEON(uint8* dst_ptr, "+r"(src_ptr), // %1 "+r"(src_stride), // %2 "+r"(dst_width), // %3 - "+r"(source_y_fraction) // %4 + "+r"(y1_fraction) // %4 : : "cc", "memory", "q0", "q1", "d4", "d5", "q13", "q14" ); @@ -2669,7 +2422,6 @@ void ARGBQuantizeRow_NEON(uint8* dst_argb, int scale, int interval_size, "vdup.u16 q10, %4 \n" // interval add // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0] \n" // load 8 pixels of ARGB. @@ -2712,7 +2464,6 @@ void ARGBShadeRow_NEON(const uint8* src_argb, uint8* dst_argb, int width, "vshr.u16 q0, q0, #1 \n" // scale / 2. // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d20, d22, d24, d26}, [%0]! \n" // load 8 pixels of ARGB. @@ -2748,7 +2499,6 @@ void ARGBGrayRow_NEON(const uint8* src_argb, uint8* dst_argb, int width) { "vmov.u8 d24, #15 \n" // B * 0.11400 coefficient "vmov.u8 d25, #75 \n" // G * 0.58700 coefficient "vmov.u8 d26, #38 \n" // R * 0.29900 coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -2785,7 +2535,6 @@ void ARGBSepiaRow_NEON(uint8* dst_argb, int width) { "vmov.u8 d28, #24 \n" // BB coefficient "vmov.u8 d29, #98 \n" // BG coefficient "vmov.u8 d30, #50 \n" // BR coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0] \n" // load 8 ARGB pixels. @@ -2824,7 +2573,6 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "vmovl.s8 q0, d4 \n" // B,G coefficients s16. "vmovl.s8 q1, d5 \n" // R,A coefficients s16. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d16, d18, d20, d22}, [%0]! \n" // load 8 ARGB pixels. @@ -2832,7 +2580,7 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "vmovl.u8 q8, d16 \n" // b (0 .. 255) 16 bit "vmovl.u8 q9, d18 \n" // g "vmovl.u8 q10, d20 \n" // r - "vmovl.u8 q15, d22 \n" // a + "vmovl.u8 q11, d22 \n" // a "vmul.s16 q12, q8, d0[0] \n" // B = B * Matrix B "vmul.s16 q13, q8, d1[0] \n" // G = B * Matrix G "vmul.s16 q14, q8, d2[0] \n" // R = B * Matrix R @@ -2853,10 +2601,10 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "vqadd.s16 q13, q13, q5 \n" // Accumulate G "vqadd.s16 q14, q14, q6 \n" // Accumulate R "vqadd.s16 q15, q15, q7 \n" // Accumulate A - "vmul.s16 q4, q15, d0[3] \n" // B += A * Matrix B - "vmul.s16 q5, q15, d1[3] \n" // G += A * Matrix G - "vmul.s16 q6, q15, d2[3] \n" // R += A * Matrix R - "vmul.s16 q7, q15, d3[3] \n" // A += A * Matrix A + "vmul.s16 q4, q11, d0[3] \n" // B += A * Matrix B + "vmul.s16 q5, q11, d1[3] \n" // G += A * Matrix G + "vmul.s16 q6, q11, d2[3] \n" // R += A * Matrix R + "vmul.s16 q7, q11, d3[3] \n" // A += A * Matrix A "vqadd.s16 q12, q12, q4 \n" // Accumulate B "vqadd.s16 q13, q13, q5 \n" // Accumulate G "vqadd.s16 q14, q14, q6 \n" // Accumulate R @@ -2872,7 +2620,7 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "+r"(dst_argb), // %1 "+r"(width) // %2 : "r"(matrix_argb) // %3 - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + : "cc", "memory", "q0", "q1", "q2", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" ); } @@ -2884,7 +2632,6 @@ void ARGBMultiplyRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -2918,7 +2665,6 @@ void ARGBAddRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -2945,7 +2691,6 @@ void ARGBSubtractRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. @@ -2977,7 +2722,6 @@ void SobelRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, asm volatile ( "vmov.u8 d3, #255 \n" // alpha // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0}, [%0]! \n" // load 8 sobelx. @@ -3004,7 +2748,6 @@ void SobelToPlaneRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_y, int width) { asm volatile ( // 16 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load 16 sobelx. @@ -3034,7 +2777,6 @@ void SobelXYRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, asm volatile ( "vmov.u8 d3, #255 \n" // alpha // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d2}, [%0]! \n" // load 8 sobelx. @@ -3061,7 +2803,6 @@ void SobelXYRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, void SobelXRow_NEON(const uint8* src_y0, const uint8* src_y1, const uint8* src_y2, uint8* dst_sobelx, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0}, [%0],%5 \n" // top @@ -3105,7 +2846,6 @@ void SobelXRow_NEON(const uint8* src_y0, const uint8* src_y1, void SobelYRow_NEON(const uint8* src_y0, const uint8* src_y1, uint8* dst_sobely, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0}, [%0],%4 \n" // left @@ -3140,7 +2880,7 @@ void SobelYRow_NEON(const uint8* src_y0, const uint8* src_y1, : "cc", "memory", "q0", "q1" // Clobber List ); } -#endif // __ARM_NEON__ +#endif // defined(__ARM_NEON__) && !defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/row_neon64.cc b/TMessagesProj/jni/libyuv/source/row_neon64.cc index 952e10d7..6fe5a108 100644 --- a/TMessagesProj/jni/libyuv/source/row_neon64.cc +++ b/TMessagesProj/jni/libyuv/source/row_neon64.cc @@ -15,146 +15,146 @@ namespace libyuv { extern "C" { #endif -// This module is for GCC Neon +// This module is for GCC Neon armv8 64 bit. #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) // Read 8 Y, 4 U and 4 V from 422 #define READYUV422 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ + "ld1 {v0.8b}, [%0], #8 \n" \ MEMACCESS(1) \ - "vld1.32 {d2[0]}, [%1]! \n" \ + "ld1 {v1.s}[0], [%1], #4 \n" \ MEMACCESS(2) \ - "vld1.32 {d2[1]}, [%2]! \n" + "ld1 {v1.s}[1], [%2], #4 \n" // Read 8 Y, 2 U and 2 V from 422 #define READYUV411 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ + "ld1 {v0.8b}, [%0], #8 \n" \ MEMACCESS(1) \ - "vld1.16 {d2[0]}, [%1]! \n" \ + "ld1 {v2.h}[0], [%1], #2 \n" \ MEMACCESS(2) \ - "vld1.16 {d2[1]}, [%2]! \n" \ - "vmov.u8 d3, d2 \n" \ - "vzip.u8 d2, d3 \n" + "ld1 {v2.h}[1], [%2], #2 \n" \ + "zip1 v1.8b, v2.8b, v2.8b \n" // Read 8 Y, 8 U and 8 V from 444 #define READYUV444 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ + "ld1 {v0.8b}, [%0], #8 \n" \ MEMACCESS(1) \ - "vld1.8 {d2}, [%1]! \n" \ + "ld1 {v1.d}[0], [%1], #8 \n" \ MEMACCESS(2) \ - "vld1.8 {d3}, [%2]! \n" \ - "vpaddl.u8 q1, q1 \n" \ - "vrshrn.u16 d2, q1, #1 \n" + "ld1 {v1.d}[1], [%2], #8 \n" \ + "uaddlp v1.8h, v1.16b \n" \ + "rshrn v1.8b, v1.8h, #1 \n" // Read 8 Y, and set 4 U and 4 V to 128 #define READYUV400 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ - "vmov.u8 d2, #128 \n" + "ld1 {v0.8b}, [%0], #8 \n" \ + "movi v1.8b , #128 \n" // Read 8 Y and 4 UV from NV12 #define READNV12 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ + "ld1 {v0.8b}, [%0], #8 \n" \ MEMACCESS(1) \ - "vld1.8 {d2}, [%1]! \n" \ - "vmov.u8 d3, d2 \n"/* split odd/even uv apart */\ - "vuzp.u8 d2, d3 \n" \ - "vtrn.u32 d2, d3 \n" + "ld1 {v2.8b}, [%1], #8 \n" \ + "uzp1 v1.8b, v2.8b, v2.8b \n" \ + "uzp2 v3.8b, v2.8b, v2.8b \n" \ + "ins v1.s[1], v3.s[0] \n" // Read 8 Y and 4 VU from NV21 #define READNV21 \ MEMACCESS(0) \ - "vld1.8 {d0}, [%0]! \n" \ + "ld1 {v0.8b}, [%0], #8 \n" \ MEMACCESS(1) \ - "vld1.8 {d2}, [%1]! \n" \ - "vmov.u8 d3, d2 \n"/* split odd/even uv apart */\ - "vuzp.u8 d3, d2 \n" \ - "vtrn.u32 d2, d3 \n" + "ld1 {v2.8b}, [%1], #8 \n" \ + "uzp1 v3.8b, v2.8b, v2.8b \n" \ + "uzp2 v1.8b, v2.8b, v2.8b \n" \ + "ins v1.s[1], v3.s[0] \n" // Read 8 YUY2 #define READYUY2 \ MEMACCESS(0) \ - "vld2.8 {d0, d2}, [%0]! \n" \ - "vmov.u8 d3, d2 \n" \ - "vuzp.u8 d2, d3 \n" \ - "vtrn.u32 d2, d3 \n" + "ld2 {v0.8b, v1.8b}, [%0], #16 \n" \ + "uzp2 v3.8b, v1.8b, v1.8b \n" \ + "uzp1 v1.8b, v1.8b, v1.8b \n" \ + "ins v1.s[1], v3.s[0] \n" // Read 8 UYVY #define READUYVY \ MEMACCESS(0) \ - "vld2.8 {d2, d3}, [%0]! \n" \ - "vmov.u8 d0, d3 \n" \ - "vmov.u8 d3, d2 \n" \ - "vuzp.u8 d2, d3 \n" \ - "vtrn.u32 d2, d3 \n" + "ld2 {v2.8b, v3.8b}, [%0], #16 \n" \ + "orr v0.8b, v3.8b, v3.8b \n" \ + "uzp1 v1.8b, v2.8b, v2.8b \n" \ + "uzp2 v3.8b, v2.8b, v2.8b \n" \ + "ins v1.s[1], v3.s[0] \n" -#define YUV422TORGB \ - "veor.u8 d2, d26 \n"/*subtract 128 from u and v*/\ - "vmull.s8 q8, d2, d24 \n"/* u/v B/R component */\ - "vmull.s8 q9, d2, d25 \n"/* u/v G component */\ - "vmov.u8 d1, #0 \n"/* split odd/even y apart */\ - "vtrn.u8 d0, d1 \n" \ - "vsub.s16 q0, q0, q15 \n"/* offset y */\ - "vmul.s16 q0, q0, q14 \n" \ - "vadd.s16 d18, d19 \n" \ - "vqadd.s16 d20, d0, d16 \n" /* B */ \ - "vqadd.s16 d21, d1, d16 \n" \ - "vqadd.s16 d22, d0, d17 \n" /* R */ \ - "vqadd.s16 d23, d1, d17 \n" \ - "vqadd.s16 d16, d0, d18 \n" /* G */ \ - "vqadd.s16 d17, d1, d18 \n" \ - "vqshrun.s16 d0, q10, #6 \n" /* B */ \ - "vqshrun.s16 d1, q11, #6 \n" /* G */ \ - "vqshrun.s16 d2, q8, #6 \n" /* R */ \ - "vmovl.u8 q10, d0 \n"/* set up for reinterleave*/\ - "vmovl.u8 q11, d1 \n" \ - "vmovl.u8 q8, d2 \n" \ - "vtrn.u8 d20, d21 \n" \ - "vtrn.u8 d22, d23 \n" \ - "vtrn.u8 d16, d17 \n" \ - "vmov.u8 d21, d16 \n" +#define YUVTORGB_SETUP \ + "ld1r {v24.8h}, [%[kUVBiasBGR]], #2 \n" \ + "ld1r {v25.8h}, [%[kUVBiasBGR]], #2 \n" \ + "ld1r {v26.8h}, [%[kUVBiasBGR]] \n" \ + "ld1r {v31.4s}, [%[kYToRgb]] \n" \ + "ld2 {v27.8h, v28.8h}, [%[kUVToRB]] \n" \ + "ld2 {v29.8h, v30.8h}, [%[kUVToG]] \n" -static vec8 kUVToRB = { 127, 127, 127, 127, 102, 102, 102, 102, - 0, 0, 0, 0, 0, 0, 0, 0 }; -static vec8 kUVToG = { -25, -25, -25, -25, -52, -52, -52, -52, - 0, 0, 0, 0, 0, 0, 0, 0 }; +#define YUVTORGB(vR, vG, vB) \ + "uxtl v0.8h, v0.8b \n" /* Extract Y */ \ + "shll v2.8h, v1.8b, #8 \n" /* Replicate UV */ \ + "ushll2 v3.4s, v0.8h, #0 \n" /* Y */ \ + "ushll v0.4s, v0.4h, #0 \n" \ + "mul v3.4s, v3.4s, v31.4s \n" \ + "mul v0.4s, v0.4s, v31.4s \n" \ + "sqshrun v0.4h, v0.4s, #16 \n" \ + "sqshrun2 v0.8h, v3.4s, #16 \n" /* Y */ \ + "uaddw v1.8h, v2.8h, v1.8b \n" /* Replicate UV */ \ + "mov v2.d[0], v1.d[1] \n" /* Extract V */ \ + "uxtl v2.8h, v2.8b \n" \ + "uxtl v1.8h, v1.8b \n" /* Extract U */ \ + "mul v3.8h, v1.8h, v27.8h \n" \ + "mul v5.8h, v1.8h, v29.8h \n" \ + "mul v6.8h, v2.8h, v30.8h \n" \ + "mul v7.8h, v2.8h, v28.8h \n" \ + "sqadd v6.8h, v6.8h, v5.8h \n" \ + "sqadd " #vB ".8h, v24.8h, v0.8h \n" /* B */ \ + "sqadd " #vG ".8h, v25.8h, v0.8h \n" /* G */ \ + "sqadd " #vR ".8h, v26.8h, v0.8h \n" /* R */ \ + "sqadd " #vB ".8h, " #vB ".8h, v3.8h \n" /* B */ \ + "sqsub " #vG ".8h, " #vG ".8h, v6.8h \n" /* G */ \ + "sqadd " #vR ".8h, " #vR ".8h, v7.8h \n" /* R */ \ + "sqshrun " #vB ".8b, " #vB ".8h, #6 \n" /* B */ \ + "sqshrun " #vG ".8b, " #vG ".8h, #6 \n" /* G */ \ + "sqshrun " #vR ".8b, " #vR ".8h, #6 \n" /* R */ \ #ifdef HAS_I444TOARGBROW_NEON void I444ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" /* A */ "1: \n" READYUV444 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" MEMACCESS(3) - "vst4.8 {d20, d21, d22, d23}, [%3]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%3], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I444TOARGBROW_NEON @@ -164,179 +164,128 @@ void I422ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" /* A */ "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" MEMACCESS(3) - "vst4.8 {d20, d21, d22, d23}, [%3]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%3], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TOARGBROW_NEON +#ifdef HAS_I422ALPHATOARGBROW_NEON +void I422AlphaToARGBRow_NEON(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + const uint8* src_a, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + asm volatile ( + YUVTORGB_SETUP + "1: \n" + READYUV422 + YUVTORGB(v22, v21, v20) + MEMACCESS(3) + "ld1 {v23.8b}, [%3], #8 \n" + "subs %w5, %w5, #8 \n" + MEMACCESS(4) + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%4], #32 \n" + "b.gt 1b \n" + : "+r"(src_y), // %0 + "+r"(src_u), // %1 + "+r"(src_v), // %2 + "+r"(src_a), // %3 + "+r"(dst_argb), // %4 + "+r"(width) // %5 + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" + ); +} +#endif // HAS_I422ALPHATOARGBROW_NEON + #ifdef HAS_I411TOARGBROW_NEON void I411ToARGBRow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" /* A */ "1: \n" READYUV411 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" MEMACCESS(3) - "vst4.8 {d20, d21, d22, d23}, [%3]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%3], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_argb), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I411TOARGBROW_NEON -#ifdef HAS_I422TOBGRAROW_NEON -void I422ToBGRARow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_bgra, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - "vmov.u8 d19, #255 \n" - MEMACCESS(3) - "vst4.8 {d19, d20, d21, d22}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_bgra), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} -#endif // HAS_I422TOBGRAROW_NEON - -#ifdef HAS_I422TOABGRROW_NEON -void I422ToABGRRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_abgr, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - "vmov.u8 d23, #255 \n" - MEMACCESS(3) - "vst4.8 {d20, d21, d22, d23}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_abgr), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} -#endif // HAS_I422TOABGRROW_NEON - #ifdef HAS_I422TORGBAROW_NEON void I422ToRGBARow_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v20.8b, #255 \n" /* A */ "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d19, #255 \n" + YUVTORGB(v23, v22, v21) + "subs %w4, %w4, #8 \n" MEMACCESS(3) - "vst4.8 {d19, d20, d21, d22}, [%3]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%3], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_rgba), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TORGBAROW_NEON @@ -346,440 +295,324 @@ void I422ToRGB24Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" MEMACCESS(3) - "vst3.8 {d20, d21, d22}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_rgb24), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + "st3 {v20.8b,v21.8b,v22.8b}, [%3], #24 \n" + "b.gt 1b \n" + : "+r"(src_y), // %0 + "+r"(src_u), // %1 + "+r"(src_v), // %2 + "+r"(dst_rgb24), // %3 + "+r"(width) // %4 + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TORGB24ROW_NEON -#ifdef HAS_I422TORAWROW_NEON -void I422ToRAWRow_NEON(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_raw, - int width) { - asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vswp.u8 d20, d22 \n" - MEMACCESS(3) - "vst3.8 {d20, d21, d22}, [%3]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_raw), // %3 - "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} -#endif // HAS_I422TORAWROW_NEON - #define ARGBTORGB565 \ - "vshr.u8 d20, d20, #3 \n" /* B */ \ - "vshr.u8 d21, d21, #2 \n" /* G */ \ - "vshr.u8 d22, d22, #3 \n" /* R */ \ - "vmovl.u8 q8, d20 \n" /* B */ \ - "vmovl.u8 q9, d21 \n" /* G */ \ - "vmovl.u8 q10, d22 \n" /* R */ \ - "vshl.u16 q9, q9, #5 \n" /* G */ \ - "vshl.u16 q10, q10, #11 \n" /* R */ \ - "vorr q0, q8, q9 \n" /* BG */ \ - "vorr q0, q0, q10 \n" /* BGR */ + "shll v0.8h, v22.8b, #8 \n" /* R */ \ + "shll v20.8h, v20.8b, #8 \n" /* B */ \ + "shll v21.8h, v21.8b, #8 \n" /* G */ \ + "sri v0.8h, v21.8h, #5 \n" /* RG */ \ + "sri v0.8h, v20.8h, #11 \n" /* RGB */ #ifdef HAS_I422TORGB565ROW_NEON void I422ToRGB565Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" ARGBTORGB565 MEMACCESS(3) - "vst1.8 {q0}, [%3]! \n" // store 8 pixels RGB565. - "bgt 1b \n" + "st1 {v0.8h}, [%3], #16 \n" // store 8 pixels RGB565. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_rgb565), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TORGB565ROW_NEON #define ARGBTOARGB1555 \ - "vshr.u8 q10, q10, #3 \n" /* B */ \ - "vshr.u8 d22, d22, #3 \n" /* R */ \ - "vshr.u8 d23, d23, #7 \n" /* A */ \ - "vmovl.u8 q8, d20 \n" /* B */ \ - "vmovl.u8 q9, d21 \n" /* G */ \ - "vmovl.u8 q10, d22 \n" /* R */ \ - "vmovl.u8 q11, d23 \n" /* A */ \ - "vshl.u16 q9, q9, #5 \n" /* G */ \ - "vshl.u16 q10, q10, #10 \n" /* R */ \ - "vshl.u16 q11, q11, #15 \n" /* A */ \ - "vorr q0, q8, q9 \n" /* BG */ \ - "vorr q1, q10, q11 \n" /* RA */ \ - "vorr q0, q0, q1 \n" /* BGRA */ + "shll v0.8h, v23.8b, #8 \n" /* A */ \ + "shll v22.8h, v22.8b, #8 \n" /* R */ \ + "shll v20.8h, v20.8b, #8 \n" /* B */ \ + "shll v21.8h, v21.8b, #8 \n" /* G */ \ + "sri v0.8h, v22.8h, #1 \n" /* AR */ \ + "sri v0.8h, v21.8h, #6 \n" /* ARG */ \ + "sri v0.8h, v20.8h, #11 \n" /* ARGB */ #ifdef HAS_I422TOARGB1555ROW_NEON void I422ToARGB1555Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb1555, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" ARGBTOARGB1555 MEMACCESS(3) - "vst1.8 {q0}, [%3]! \n" // store 8 pixels ARGB1555. - "bgt 1b \n" + "st1 {v0.8h}, [%3], #16 \n" // store 8 pixels RGB565. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_argb1555), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TOARGB1555ROW_NEON #define ARGBTOARGB4444 \ - "vshr.u8 d20, d20, #4 \n" /* B */ \ - "vbic.32 d21, d21, d4 \n" /* G */ \ - "vshr.u8 d22, d22, #4 \n" /* R */ \ - "vbic.32 d23, d23, d4 \n" /* A */ \ - "vorr d0, d20, d21 \n" /* BG */ \ - "vorr d1, d22, d23 \n" /* RA */ \ - "vzip.u8 d0, d1 \n" /* BGRA */ + /* Input v20.8b<=B, v21.8b<=G, v22.8b<=R, v23.8b<=A, v4.8b<=0x0f */ \ + "ushr v20.8b, v20.8b, #4 \n" /* B */ \ + "bic v21.8b, v21.8b, v4.8b \n" /* G */ \ + "ushr v22.8b, v22.8b, #4 \n" /* R */ \ + "bic v23.8b, v23.8b, v4.8b \n" /* A */ \ + "orr v0.8b, v20.8b, v21.8b \n" /* BG */ \ + "orr v1.8b, v22.8b, v23.8b \n" /* RA */ \ + "zip1 v0.16b, v0.16b, v1.16b \n" /* BGRA */ #ifdef HAS_I422TOARGB4444ROW_NEON void I422ToARGB4444Row_NEON(const uint8* src_y, const uint8* src_u, const uint8* src_v, uint8* dst_argb4444, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(5) - "vld1.8 {d24}, [%5] \n" - MEMACCESS(6) - "vld1.8 {d25}, [%6] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - "vmov.u8 d4, #0x0f \n" // bits to clear with vbic. - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v4.16b, #0x0f \n" // bits to clear with vbic. "1: \n" READYUV422 - YUV422TORGB - "subs %4, %4, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w4, %w4, #8 \n" + "movi v23.8b, #255 \n" ARGBTOARGB4444 MEMACCESS(3) - "vst1.8 {q0}, [%3]! \n" // store 8 pixels ARGB4444. - "bgt 1b \n" + "st1 {v0.8h}, [%3], #16 \n" // store 8 pixels ARGB4444. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 "+r"(dst_argb4444), // %3 "+r"(width) // %4 - : "r"(&kUVToRB), // %5 - "r"(&kUVToG) // %6 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_I422TOARGB4444ROW_NEON -#ifdef HAS_YTOARGBROW_NEON -void YToARGBRow_NEON(const uint8* src_y, - uint8* dst_argb, - int width) { - asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READYUV400 - YUV422TORGB - "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" - MEMACCESS(1) - "vst4.8 {d20, d21, d22, d23}, [%1]! \n" - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} -#endif // HAS_YTOARGBROW_NEON - #ifdef HAS_I400TOARGBROW_NEON void I400ToARGBRow_NEON(const uint8* src_y, uint8* dst_argb, int width) { + int64 width64 = (int64)(width); asm volatile ( - ".p2align 2 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" + "1: \n" + READYUV400 + YUVTORGB(v22, v21, v20) + "subs %w2, %w2, #8 \n" + MEMACCESS(1) + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%1], #32 \n" + "b.gt 1b \n" + : "+r"(src_y), // %0 + "+r"(dst_argb), // %1 + "+r"(width64) // %2 + : [kUVToRB]"r"(&kYuvI601Constants.kUVToRB), + [kUVToG]"r"(&kYuvI601Constants.kUVToG), + [kUVBiasBGR]"r"(&kYuvI601Constants.kUVBiasBGR), + [kYToRgb]"r"(&kYuvI601Constants.kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" + ); +} +#endif // HAS_I400TOARGBROW_NEON + +#ifdef HAS_J400TOARGBROW_NEON +void J400ToARGBRow_NEON(const uint8* src_y, + uint8* dst_argb, + int width) { + asm volatile ( + "movi v23.8b, #255 \n" "1: \n" MEMACCESS(0) - "vld1.8 {d20}, [%0]! \n" - "vmov d21, d20 \n" - "vmov d22, d20 \n" - "subs %2, %2, #8 \n" + "ld1 {v20.8b}, [%0], #8 \n" + "orr v21.8b, v20.8b, v20.8b \n" + "orr v22.8b, v20.8b, v20.8b \n" + "subs %w2, %w2, #8 \n" MEMACCESS(1) - "vst4.8 {d20, d21, d22, d23}, [%1]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%1], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 : - : "cc", "memory", "d20", "d21", "d22", "d23" + : "cc", "memory", "v20", "v21", "v22", "v23" ); } -#endif // HAS_I400TOARGBROW_NEON +#endif // HAS_J400TOARGBROW_NEON #ifdef HAS_NV12TOARGBROW_NEON void NV12ToARGBRow_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" "1: \n" READNV12 - YUV422TORGB - "subs %3, %3, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w3, %w3, #8 \n" MEMACCESS(2) - "vst4.8 {d20, d21, d22, d23}, [%2]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%2], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_uv), // %1 "+r"(dst_argb), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_NV12TOARGBROW_NEON -#ifdef HAS_NV21TOARGBROW_NEON +#ifdef HAS_NV12TOARGBROW_NEON void NV21ToARGBRow_NEON(const uint8* src_y, - const uint8* src_uv, + const uint8* src_vu, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" "1: \n" READNV21 - YUV422TORGB - "subs %3, %3, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w3, %w3, #8 \n" MEMACCESS(2) - "vst4.8 {d20, d21, d22, d23}, [%2]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%2], #32 \n" + "b.gt 1b \n" : "+r"(src_y), // %0 - "+r"(src_uv), // %1 + "+r"(src_vu), // %1 "+r"(dst_argb), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } -#endif // HAS_NV21TOARGBROW_NEON +#endif // HAS_NV12TOARGBROW_NEON #ifdef HAS_NV12TORGB565ROW_NEON void NV12ToRGB565Row_NEON(const uint8* src_y, const uint8* src_uv, uint8* dst_rgb565, + const struct YuvConstants* yuvconstants, int width) { asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP "1: \n" READNV12 - YUV422TORGB - "subs %3, %3, #8 \n" + YUVTORGB(v22, v21, v20) + "subs %w3, %w3, #8 \n" ARGBTORGB565 MEMACCESS(2) - "vst1.8 {q0}, [%2]! \n" // store 8 pixels RGB565. - "bgt 1b \n" + "st1 {v0.8h}, [%2], 16 \n" // store 8 pixels RGB565. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_uv), // %1 "+r"(dst_rgb565), // %2 "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_NV12TORGB565ROW_NEON -#ifdef HAS_NV21TORGB565ROW_NEON -void NV21ToRGB565Row_NEON(const uint8* src_y, - const uint8* src_uv, - uint8* dst_rgb565, - int width) { - asm volatile ( - MEMACCESS(4) - "vld1.8 {d24}, [%4] \n" - MEMACCESS(5) - "vld1.8 {d25}, [%5] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" - "1: \n" - READNV21 - YUV422TORGB - "subs %3, %3, #8 \n" - ARGBTORGB565 - MEMACCESS(2) - "vst1.8 {q0}, [%2]! \n" // store 8 pixels RGB565. - "bgt 1b \n" - : "+r"(src_y), // %0 - "+r"(src_uv), // %1 - "+r"(dst_rgb565), // %2 - "+r"(width) // %3 - : "r"(&kUVToRB), // %4 - "r"(&kUVToG) // %5 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" - ); -} -#endif // HAS_NV21TORGB565ROW_NEON - #ifdef HAS_YUY2TOARGBROW_NEON void YUY2ToARGBRow_NEON(const uint8* src_yuy2, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { + int64 width64 = (int64)(width); asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" "1: \n" READYUY2 - YUV422TORGB - "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w2, %w2, #8 \n" MEMACCESS(1) - "vst4.8 {d20, d21, d22, d23}, [%1]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%1], #32 \n" + "b.gt 1b \n" : "+r"(src_yuy2), // %0 "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + "+r"(width64) // %2 + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_YUY2TOARGBROW_NEON @@ -787,31 +620,28 @@ void YUY2ToARGBRow_NEON(const uint8* src_yuy2, #ifdef HAS_UYVYTOARGBROW_NEON void UYVYToARGBRow_NEON(const uint8* src_uyvy, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { + int64 width64 = (int64)(width); asm volatile ( - MEMACCESS(3) - "vld1.8 {d24}, [%3] \n" - MEMACCESS(4) - "vld1.8 {d25}, [%4] \n" - "vmov.u8 d26, #128 \n" - "vmov.u16 q14, #74 \n" - "vmov.u16 q15, #16 \n" - ".p2align 2 \n" + YUVTORGB_SETUP + "movi v23.8b, #255 \n" "1: \n" READUYVY - YUV422TORGB - "subs %2, %2, #8 \n" - "vmov.u8 d23, #255 \n" + YUVTORGB(v22, v21, v20) + "subs %w2, %w2, #8 \n" MEMACCESS(1) - "vst4.8 {d20, d21, d22, d23}, [%1]! \n" - "bgt 1b \n" + "st4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%1], 32 \n" + "b.gt 1b \n" : "+r"(src_uyvy), // %0 "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(&kUVToRB), // %3 - "r"(&kUVToG) // %4 - : "cc", "memory", "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + "+r"(width64) // %2 + : [kUVToRB]"r"(&yuvconstants->kUVToRB), + [kUVToG]"r"(&yuvconstants->kUVToG), + [kUVBiasBGR]"r"(&yuvconstants->kUVBiasBGR), + [kYToRgb]"r"(&yuvconstants->kYToRgb) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30" ); } #endif // HAS_UYVYTOARGBROW_NEON @@ -821,16 +651,15 @@ void UYVYToARGBRow_NEON(const uint8* src_uyvy, void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld2 {v0.16b, v1.16b}, [%0], #32 \n" // load 16 pairs of UV - "subs %3, %3, #16 \n" // 16 processed per loop + "ld2 {v0.16b,v1.16b}, [%0], #32 \n" // load 16 pairs of UV + "subs %w3, %w3, #16 \n" // 16 processed per loop MEMACCESS(1) "st1 {v0.16b}, [%1], #16 \n" // store U MEMACCESS(2) "st1 {v1.16b}, [%2], #16 \n" // store V - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_uv), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 @@ -846,16 +675,15 @@ void SplitUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, void MergeUVRow_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.16b}, [%0], #16 \n" // load U MEMACCESS(1) "ld1 {v1.16b}, [%1], #16 \n" // load V - "subs %3, %3, #16 \n" // 16 processed per loop + "subs %w3, %w3, #16 \n" // 16 processed per loop MEMACCESS(2) - "st2 {v0.16b, v1.16b}, [%2], #32 \n" // store 16 pairs of UV - "bgt 1b \n" + "st2 {v0.16b,v1.16b}, [%2], #32 \n" // store 16 pairs of UV + "b.gt 1b \n" : "+r"(src_u), // %0 "+r"(src_v), // %1 @@ -871,14 +699,13 @@ void MergeUVRow_NEON(const uint8* src_u, const uint8* src_v, uint8* dst_uv, #ifdef HAS_COPYROW_NEON void CopyRow_NEON(const uint8* src, uint8* dst, int count) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld1 {v0.8b-v3.8b}, [%0], #32 \n" // load 32 - "subs %2, %2, #32 \n" // 32 processed per loop + "ld1 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 32 + "subs %w2, %w2, #32 \n" // 32 processed per loop MEMACCESS(1) - "st1 {v0.8b-v3.8b}, [%1], #32 \n" // store 32 - "bgt 1b \n" + "st1 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 32 + "b.gt 1b \n" : "+r"(src), // %0 "+r"(dst), // %1 "+r"(count) // %2 // Output registers @@ -888,57 +715,58 @@ void CopyRow_NEON(const uint8* src, uint8* dst, int count) { } #endif // HAS_COPYROW_NEON -// SetRow8 writes 'count' bytes using a 32 bit value repeated. -#ifdef HAS_SETROW_NEON -void SetRow_NEON(uint8* dst, uint32 v32, int count) { +// SetRow writes 'count' bytes using an 8 bit value repeated. +void SetRow_NEON(uint8* dst, uint8 v8, int count) { asm volatile ( - "dup v0.4s, %w2 \n" // duplicate 4 ints - "1: \n" - "subs %1, %1, #16 \n" // 16 bytes per loop + "dup v0.16b, %w2 \n" // duplicate 16 bytes + "1: \n" + "subs %w1, %w1, #16 \n" // 16 bytes per loop MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" // store - "bgt 1b \n" + "b.gt 1b \n" + : "+r"(dst), // %0 + "+r"(count) // %1 + : "r"(v8) // %2 + : "cc", "memory", "v0" + ); +} + +void ARGBSetRow_NEON(uint8* dst, uint32 v32, int count) { + asm volatile ( + "dup v0.4s, %w2 \n" // duplicate 4 ints + "1: \n" + "subs %w1, %w1, #4 \n" // 4 ints per loop + MEMACCESS(0) + "st1 {v0.16b}, [%0], #16 \n" // store + "b.gt 1b \n" : "+r"(dst), // %0 "+r"(count) // %1 : "r"(v32) // %2 : "cc", "memory", "v0" ); } -#endif // HAS_SETROW_NEON - -// TODO(fbarchard): Make fully assembler -// SetRow32 writes 'count' words using a 32 bit value repeated. -#ifdef HAS_ARGBSETROWS_NEON -void ARGBSetRows_NEON(uint8* dst, uint32 v32, int width, - int dst_stride, int height) { - for (int y = 0; y < height; ++y) { - SetRow_NEON(dst, v32, width << 2); - dst += dst_stride; - } -} -#endif // HAS_ARGBSETROWS_NEON #ifdef HAS_MIRRORROW_NEON void MirrorRow_NEON(const uint8* src, uint8* dst, int width) { + int64 width64 = (int64) width; asm volatile ( // Start at end of source row. "add %0, %0, %2 \n" "sub %0, %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.16b}, [%0], %3 \n" // src -= 16 - "subs %2, %2, #16 \n" // 16 pixels per loop. + "subs %2, %2, #16 \n" // 16 pixels per loop. "rev64 v0.16b, v0.16b \n" MEMACCESS(1) "st1 {v0.D}[1], [%1], #8 \n" // dst += 16 MEMACCESS(1) "st1 {v0.D}[0], [%1], #8 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src), // %0 "+r"(dst), // %1 - "+r"(width) // %2 + "+r"(width64) // %2 : "r"((ptrdiff_t)-16) // %3 : "cc", "memory", "v0" ); @@ -948,12 +776,12 @@ void MirrorRow_NEON(const uint8* src, uint8* dst, int width) { #ifdef HAS_MIRRORUVROW_NEON void MirrorUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) { + int64 width64 = (int64) width; asm volatile ( // Start at end of source row. "add %0, %0, %3, lsl #1 \n" "sub %0, %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld2 {v0.8b, v1.8b}, [%0], %4 \n" // src -= 16 @@ -961,14 +789,14 @@ void MirrorUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, "rev64 v0.8b, v0.8b \n" "rev64 v1.8b, v1.8b \n" MEMACCESS(1) - "st1 {v0.8b}, [%1], #8 \n" // dst += 8 + "st1 {v0.8b}, [%1], #8 \n" // dst += 8 MEMACCESS(2) - "st1 {v1.8b}, [%2], #8 \n" - "bgt 1b \n" + "st1 {v1.8b}, [%2], #8 \n" + "b.gt 1b \n" : "+r"(src_uv), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(width) // %3 + "+r"(width64) // %3 : "r"((ptrdiff_t)-16) // %4 : "cc", "memory", "v0", "v1" ); @@ -977,12 +805,12 @@ void MirrorUVRow_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, #ifdef HAS_ARGBMIRRORROW_NEON void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width) { + int64 width64 = (int64) width; asm volatile ( // Start at end of source row. "add %0, %0, %2, lsl #2 \n" "sub %0, %0, #16 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.16b}, [%0], %3 \n" // src -= 16 @@ -992,10 +820,10 @@ void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width) { "st1 {v0.D}[1], [%1], #8 \n" // dst += 16 MEMACCESS(1) "st1 {v0.D}[0], [%1], #8 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src), // %0 "+r"(dst), // %1 - "+r"(width) // %2 + "+r"(width64) // %2 : "r"((ptrdiff_t)-16) // %3 : "cc", "memory", "v0" ); @@ -1003,20 +831,19 @@ void ARGBMirrorRow_NEON(const uint8* src, uint8* dst, int width) { #endif // HAS_ARGBMIRRORROW_NEON #ifdef HAS_RGB24TOARGBROW_NEON -void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix) { +void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int width) { asm volatile ( "movi v4.8b, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld3 {v1.8b-v3.8b}, [%0], #24 \n" // load 8 pixels of RGB24. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld3 {v1.8b,v2.8b,v3.8b}, [%0], #24 \n" // load 8 pixels of RGB24. + "subs %w2, %w2, #8 \n" // 8 processed per loop. MEMACCESS(1) - "st4 {v1.8b-v4.8b}, [%1], #32 \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v1.8b,v2.8b,v3.8b,v4.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_rgb24), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v1", "v2", "v3", "v4" // Clobber List ); @@ -1024,159 +851,185 @@ void RGB24ToARGBRow_NEON(const uint8* src_rgb24, uint8* dst_argb, int pix) { #endif // HAS_RGB24TOARGBROW_NEON #ifdef HAS_RAWTOARGBROW_NEON -void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int pix) { +void RAWToARGBRow_NEON(const uint8* src_raw, uint8* dst_argb, int width) { asm volatile ( "movi v5.8b, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld3 {v0.8b-v2.8b}, [%0], #24 \n" // read r g b - "subs %2, %2, #8 \n" // 8 processed per loop. - "mov v3.8b, v1.8b \n" // move g - "mov v4.8b, v0.8b \n" // move r + "ld3 {v0.8b,v1.8b,v2.8b}, [%0], #24 \n" // read r g b + "subs %w2, %w2, #8 \n" // 8 processed per loop. + "orr v3.8b, v1.8b, v1.8b \n" // move g + "orr v4.8b, v0.8b, v0.8b \n" // move r MEMACCESS(1) - "st4 {v2.8b-v5.8b}, [%1], #32 \n" // store b g r a - "bgt 1b \n" + "st4 {v2.8b,v3.8b,v4.8b,v5.8b}, [%1], #32 \n" // store b g r a + "b.gt 1b \n" : "+r"(src_raw), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5" // Clobber List ); } #endif // HAS_RAWTOARGBROW_NEON -#define RGB565TOARGB \ - "vshrn.u16 d6, q0, #5 \n" /* G xxGGGGGG */ \ - "vuzp.u8 d0, d1 \n" /* d0 xxxBBBBB RRRRRxxx */ \ - "vshl.u8 d6, d6, #2 \n" /* G GGGGGG00 upper 6 */ \ - "vshr.u8 d1, d1, #3 \n" /* R 000RRRRR lower 5 */ \ - "vshl.u8 q0, q0, #3 \n" /* B,R BBBBB000 upper 5 */ \ - "vshr.u8 q2, q0, #5 \n" /* B,R 00000BBB lower 3 */ \ - "vorr.u8 d0, d0, d4 \n" /* B */ \ - "vshr.u8 d4, d6, #6 \n" /* G 000000GG lower 2 */ \ - "vorr.u8 d2, d1, d5 \n" /* R */ \ - "vorr.u8 d1, d4, d6 \n" /* G */ - -#ifdef HAS_RGB565TOARGBROW_NEON -void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int pix) { +void RAWToRGB24Row_NEON(const uint8* src_raw, uint8* dst_rgb24, int width) { asm volatile ( - "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld3 {v0.8b,v1.8b,v2.8b}, [%0], #24 \n" // read r g b + "subs %w2, %w2, #8 \n" // 8 processed per loop. + "orr v3.8b, v1.8b, v1.8b \n" // move g + "orr v4.8b, v0.8b, v0.8b \n" // move r + MEMACCESS(1) + "st3 {v2.8b,v3.8b,v4.8b}, [%1], #24 \n" // store b g r + "b.gt 1b \n" + : "+r"(src_raw), // %0 + "+r"(dst_rgb24), // %1 + "+r"(width) // %2 + : + : "cc", "memory", "v0", "v1", "v2", "v3", "v4" // Clobber List + ); +} + +#define RGB565TOARGB \ + "shrn v6.8b, v0.8h, #5 \n" /* G xxGGGGGG */ \ + "shl v6.8b, v6.8b, #2 \n" /* G GGGGGG00 upper 6 */ \ + "ushr v4.8b, v6.8b, #6 \n" /* G 000000GG lower 2 */ \ + "orr v1.8b, v4.8b, v6.8b \n" /* G */ \ + "xtn v2.8b, v0.8h \n" /* B xxxBBBBB */ \ + "ushr v0.8h, v0.8h, #11 \n" /* R 000RRRRR */ \ + "xtn2 v2.16b,v0.8h \n" /* R in upper part */ \ + "shl v2.16b, v2.16b, #3 \n" /* R,B BBBBB000 upper 5 */ \ + "ushr v0.16b, v2.16b, #5 \n" /* R,B 00000BBB lower 3 */ \ + "orr v0.16b, v0.16b, v2.16b \n" /* R,B */ \ + "dup v2.2D, v0.D[1] \n" /* R */ + +#ifdef HAS_RGB565TOARGBROW_NEON +void RGB565ToARGBRow_NEON(const uint8* src_rgb565, uint8* dst_argb, int width) { + asm volatile ( + "movi v3.8b, #255 \n" // Alpha + "1: \n" + MEMACCESS(0) + "ld1 {v0.16b}, [%0], #16 \n" // load 8 RGB565 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. RGB565TOARGB MEMACCESS(1) - "vst4.8 {d0, d1, d2, d3}, [%1]! \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_rgb565), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2", "q3" // Clobber List + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v6" // Clobber List ); } #endif // HAS_RGB565TOARGBROW_NEON #define ARGB1555TOARGB \ - "vshrn.u16 d7, q0, #8 \n" /* A Arrrrrxx */ \ - "vshr.u8 d6, d7, #2 \n" /* R xxxRRRRR */ \ - "vshrn.u16 d5, q0, #5 \n" /* G xxxGGGGG */ \ - "vmovn.u16 d4, q0 \n" /* B xxxBBBBB */ \ - "vshr.u8 d7, d7, #7 \n" /* A 0000000A */ \ - "vneg.s8 d7, d7 \n" /* A AAAAAAAA upper 8 */ \ - "vshl.u8 d6, d6, #3 \n" /* R RRRRR000 upper 5 */ \ - "vshr.u8 q1, q3, #5 \n" /* R,A 00000RRR lower 3 */ \ - "vshl.u8 q0, q2, #3 \n" /* B,G BBBBB000 upper 5 */ \ - "vshr.u8 q2, q0, #5 \n" /* B,G 00000BBB lower 3 */ \ - "vorr.u8 q1, q1, q3 \n" /* R,A */ \ - "vorr.u8 q0, q0, q2 \n" /* B,G */ \ + "ushr v2.8h, v0.8h, #10 \n" /* R xxxRRRRR */ \ + "shl v2.8h, v2.8h, #3 \n" /* R RRRRR000 upper 5 */ \ + "xtn v3.8b, v2.8h \n" /* RRRRR000 AAAAAAAA */ \ + \ + "sshr v2.8h, v0.8h, #15 \n" /* A AAAAAAAA */ \ + "xtn2 v3.16b, v2.8h \n" \ + \ + "xtn v2.8b, v0.8h \n" /* B xxxBBBBB */ \ + "shrn2 v2.16b,v0.8h, #5 \n" /* G xxxGGGGG */ \ + \ + "ushr v1.16b, v3.16b, #5 \n" /* R,A 00000RRR lower 3 */ \ + "shl v0.16b, v2.16b, #3 \n" /* B,G BBBBB000 upper 5 */ \ + "ushr v2.16b, v0.16b, #5 \n" /* B,G 00000BBB lower 3 */ \ + \ + "orr v0.16b, v0.16b, v2.16b \n" /* B,G */ \ + "orr v2.16b, v1.16b, v3.16b \n" /* R,A */ \ + "dup v1.2D, v0.D[1] \n" \ + "dup v3.2D, v2.D[1] \n" // RGB555TOARGB is same as ARGB1555TOARGB but ignores alpha. #define RGB555TOARGB \ - "vshrn.u16 d6, q0, #5 \n" /* G xxxGGGGG */ \ - "vuzp.u8 d0, d1 \n" /* d0 xxxBBBBB xRRRRRxx */ \ - "vshl.u8 d6, d6, #3 \n" /* G GGGGG000 upper 5 */ \ - "vshr.u8 d1, d1, #2 \n" /* R 00xRRRRR lower 5 */ \ - "vshl.u8 q0, q0, #3 \n" /* B,R BBBBB000 upper 5 */ \ - "vshr.u8 q2, q0, #5 \n" /* B,R 00000BBB lower 3 */ \ - "vorr.u8 d0, d0, d4 \n" /* B */ \ - "vshr.u8 d4, d6, #5 \n" /* G 00000GGG lower 3 */ \ - "vorr.u8 d2, d1, d5 \n" /* R */ \ - "vorr.u8 d1, d4, d6 \n" /* G */ + "ushr v2.8h, v0.8h, #10 \n" /* R xxxRRRRR */ \ + "shl v2.8h, v2.8h, #3 \n" /* R RRRRR000 upper 5 */ \ + "xtn v3.8b, v2.8h \n" /* RRRRR000 */ \ + \ + "xtn v2.8b, v0.8h \n" /* B xxxBBBBB */ \ + "shrn2 v2.16b,v0.8h, #5 \n" /* G xxxGGGGG */ \ + \ + "ushr v1.16b, v3.16b, #5 \n" /* R 00000RRR lower 3 */ \ + "shl v0.16b, v2.16b, #3 \n" /* B,G BBBBB000 upper 5 */ \ + "ushr v2.16b, v0.16b, #5 \n" /* B,G 00000BBB lower 3 */ \ + \ + "orr v0.16b, v0.16b, v2.16b \n" /* B,G */ \ + "orr v2.16b, v1.16b, v3.16b \n" /* R */ \ + "dup v1.2D, v0.D[1] \n" /* G */ \ #ifdef HAS_ARGB1555TOARGBROW_NEON void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, - int pix) { + int width) { asm volatile ( - "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" + "movi v3.8b, #255 \n" // Alpha "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB1555 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGB1555TOARGB MEMACCESS(1) - "vst4.8 {d0, d1, d2, d3}, [%1]! \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb1555), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2", "q3" // Clobber List + : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List ); } #endif // HAS_ARGB1555TOARGBROW_NEON #define ARGB4444TOARGB \ - "vuzp.u8 d0, d1 \n" /* d0 BG, d1 RA */ \ - "vshl.u8 q2, q0, #4 \n" /* B,R BBBB0000 */ \ - "vshr.u8 q1, q0, #4 \n" /* G,A 0000GGGG */ \ - "vshr.u8 q0, q2, #4 \n" /* B,R 0000BBBB */ \ - "vorr.u8 q0, q0, q2 \n" /* B,R BBBBBBBB */ \ - "vshl.u8 q2, q1, #4 \n" /* G,A GGGG0000 */ \ - "vorr.u8 q1, q1, q2 \n" /* G,A GGGGGGGG */ \ - "vswp.u8 d1, d2 \n" /* B,R,G,A -> B,G,R,A */ + "shrn v1.8b, v0.8h, #8 \n" /* v1(l) AR */ \ + "xtn2 v1.16b, v0.8h \n" /* v1(h) GB */ \ + "shl v2.16b, v1.16b, #4 \n" /* B,R BBBB0000 */ \ + "ushr v3.16b, v1.16b, #4 \n" /* G,A 0000GGGG */ \ + "ushr v0.16b, v2.16b, #4 \n" /* B,R 0000BBBB */ \ + "shl v1.16b, v3.16b, #4 \n" /* G,A GGGG0000 */ \ + "orr v2.16b, v0.16b, v2.16b \n" /* B,R BBBBBBBB */ \ + "orr v3.16b, v1.16b, v3.16b \n" /* G,A GGGGGGGG */ \ + "dup v0.2D, v2.D[1] \n" \ + "dup v1.2D, v3.D[1] \n" #ifdef HAS_ARGB4444TOARGBROW_NEON void ARGB4444ToARGBRow_NEON(const uint8* src_argb4444, uint8* dst_argb, - int pix) { + int width) { asm volatile ( - "vmov.u8 d3, #255 \n" // Alpha - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB4444 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGB4444TOARGB MEMACCESS(1) - "vst4.8 {d0, d1, d2, d3}, [%1]! \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb4444), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2" // Clobber List + : "cc", "memory", "v0", "v1", "v2", "v3", "v4" // Clobber List ); } #endif // HAS_ARGB4444TOARGBROW_NEON #ifdef HAS_ARGBTORGB24ROW_NEON -void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int pix) { +void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v1.8b-v4.8b}, [%0], #32 \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v1.8b,v2.8b,v3.8b,v4.8b}, [%0], #32 \n" // load 8 ARGB pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop. MEMACCESS(1) - "st3 {v1.8b-v3.8b}, [%1], #24 \n" // store 8 pixels of RGB24. - "bgt 1b \n" + "st3 {v1.8b,v2.8b,v3.8b}, [%1], #24 \n" // store 8 pixels of RGB24. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_rgb24), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v1", "v2", "v3", "v4" // Clobber List ); @@ -1184,21 +1037,20 @@ void ARGBToRGB24Row_NEON(const uint8* src_argb, uint8* dst_rgb24, int pix) { #endif // HAS_ARGBTORGB24ROW_NEON #ifdef HAS_ARGBTORAWROW_NEON -void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int pix) { +void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v1.8b-v4.8b}, [%0], #32 \n" // load b g r a - "subs %2, %2, #8 \n" // 8 processed per loop. - "mov v4.8b, v2.8b \n" // mov g - "mov v5.8b, v1.8b \n" // mov b + "ld4 {v1.8b,v2.8b,v3.8b,v4.8b}, [%0], #32 \n" // load b g r a + "subs %w2, %w2, #8 \n" // 8 processed per loop. + "orr v4.8b, v2.8b, v2.8b \n" // mov g + "orr v5.8b, v1.8b, v1.8b \n" // mov b MEMACCESS(1) - "st3 {v3.8b-v5.8b}, [%1], #24 \n" // store r g b - "bgt 1b \n" + "st3 {v3.8b,v4.8b,v5.8b}, [%1], #24 \n" // store r g b + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_raw), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v1", "v2", "v3", "v4", "v5" // Clobber List ); @@ -1206,19 +1058,18 @@ void ARGBToRAWRow_NEON(const uint8* src_argb, uint8* dst_raw, int pix) { #endif // HAS_ARGBTORAWROW_NEON #ifdef HAS_YUY2TOYROW_NEON -void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int pix) { +void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld2 {v0.16b, v1.16b}, [%0], #32 \n" // load 16 pixels of YUY2. - "subs %2, %2, #16 \n" // 16 processed per loop. + "ld2 {v0.16b,v1.16b}, [%0], #32 \n" // load 16 pixels of YUY2. + "subs %w2, %w2, #16 \n" // 16 processed per loop. MEMACCESS(1) "st1 {v0.16b}, [%1], #16 \n" // store 16 pixels of Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_yuy2), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1" // Clobber List ); @@ -1226,19 +1077,18 @@ void YUY2ToYRow_NEON(const uint8* src_yuy2, uint8* dst_y, int pix) { #endif // HAS_YUY2TOYROW_NEON #ifdef HAS_UYVYTOYROW_NEON -void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int pix) { +void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld2 {v0.16b, v1.16b}, [%0], #32 \n" // load 16 pixels of UYVY. - "subs %2, %2, #16 \n" // 16 processed per loop. + "ld2 {v0.16b,v1.16b}, [%0], #32 \n" // load 16 pixels of UYVY. + "subs %w2, %w2, #16 \n" // 16 processed per loop. MEMACCESS(1) "st1 {v1.16b}, [%1], #16 \n" // store 16 pixels of Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_uyvy), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1" // Clobber List ); @@ -1247,22 +1097,21 @@ void UYVYToYRow_NEON(const uint8* src_uyvy, uint8* dst_y, int pix) { #ifdef HAS_YUY2TOUV422ROW_NEON void YUY2ToUV422Row_NEON(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 16 pixels of YUY2. - "subs %3, %3, #16 \n" // 16 pixels = 8 UVs. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 16 YUY2 pixels + "subs %w3, %w3, #16 \n" // 16 pixels = 8 UVs. MEMACCESS(1) "st1 {v1.8b}, [%1], #8 \n" // store 8 U. MEMACCESS(2) "st1 {v3.8b}, [%2], #8 \n" // store 8 V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_yuy2), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List ); @@ -1271,22 +1120,21 @@ void YUY2ToUV422Row_NEON(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v, #ifdef HAS_UYVYTOUV422ROW_NEON void UYVYToUV422Row_NEON(const uint8* src_uyvy, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 16 pixels of UYVY. - "subs %3, %3, #16 \n" // 16 pixels = 8 UVs. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 16 UYVY pixels + "subs %w3, %w3, #16 \n" // 16 pixels = 8 UVs. MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 U. MEMACCESS(2) "st1 {v2.8b}, [%2], #8 \n" // store 8 V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_uyvy), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List ); @@ -1295,154 +1143,82 @@ void UYVYToUV422Row_NEON(const uint8* src_uyvy, uint8* dst_u, uint8* dst_v, #ifdef HAS_YUY2TOUVROW_NEON void YUY2ToUVRow_NEON(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_yuy2b = src_yuy2 + stride_yuy2; asm volatile ( - "add %x1, %x0, %w1, sxtw \n" // stride + src_yuy2 - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 16 pixels of YUY2. - "subs %4, %4, #16 \n" // 16 pixels = 8 UVs. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 16 pixels + "subs %w4, %w4, #16 \n" // 16 pixels = 8 UVs. MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load next row YUY2. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load next row "urhadd v1.8b, v1.8b, v5.8b \n" // average rows of U "urhadd v3.8b, v3.8b, v7.8b \n" // average rows of V MEMACCESS(2) "st1 {v1.8b}, [%2], #8 \n" // store 8 U. MEMACCESS(3) "st1 {v3.8b}, [%3], #8 \n" // store 8 V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_yuy2), // %0 - "+r"(stride_yuy2), // %1 + "+r"(src_yuy2b), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7" // Clobber List + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", + "v5", "v6", "v7" // Clobber List ); } #endif // HAS_YUY2TOUVROW_NEON #ifdef HAS_UYVYTOUVROW_NEON void UYVYToUVRow_NEON(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_uyvyb = src_uyvy + stride_uyvy; asm volatile ( - "add %x1, %x0, %w1, sxtw \n" // stride + src_uyvy - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 16 pixels of UYVY. - "subs %4, %4, #16 \n" // 16 pixels = 8 UVs. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 16 pixels + "subs %w4, %w4, #16 \n" // 16 pixels = 8 UVs. MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load next row UYVY. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load next row "urhadd v0.8b, v0.8b, v4.8b \n" // average rows of U "urhadd v2.8b, v2.8b, v6.8b \n" // average rows of V MEMACCESS(2) "st1 {v0.8b}, [%2], #8 \n" // store 8 U. MEMACCESS(3) "st1 {v2.8b}, [%3], #8 \n" // store 8 V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_uyvy), // %0 - "+r"(stride_uyvy), // %1 + "+r"(src_uyvyb), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7" // Clobber List + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", + "v5", "v6", "v7" // Clobber List ); } #endif // HAS_UYVYTOUVROW_NEON -#ifdef HAS_HALFROW_NEON -void HalfRow_NEON(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { - asm volatile ( - // change the stride to row 2 pointer - "add %x1, %x0, %w1, sxtw \n" - "1: \n" - MEMACCESS(0) - "ld1 {v0.16b}, [%0], #16 \n" // load row 1 16 pixels. - "subs %3, %3, #16 \n" // 16 processed per loop - MEMACCESS(1) - "ld1 {v1.16b}, [%1], #16 \n" // load row 2 16 pixels. - "urhadd v0.16b, v0.16b, v1.16b \n" // average row 1 and 2 - MEMACCESS(2) - "st1 {v0.16b}, [%2], #16 \n" - "bgt 1b \n" - : "+r"(src_uv), // %0 - "+r"(src_uv_stride), // %1 - "+r"(dst_uv), // %2 - "+r"(pix) // %3 - : - : "cc", "memory", "v0", "v1" // Clobber List - ); -} -#endif // HAS_HALFROW_NEON - -// Select 2 channels from ARGB on alternating pixels. e.g. BGBGBGBG -#ifdef HAS_ARGBTOBAYERROW_NEON -void ARGBToBayerRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - asm volatile ( - "mov v2.s[0], %w3 \n" // selector - "1: \n" - MEMACCESS(0) - "ld1 {v0.16b, v1.16b}, [%0], 32 \n" // load row 8 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop - "tbl v4.8b, {v0.16b}, v2.8b \n" // look up 4 pixels - "tbl v5.8b, {v1.16b}, v2.8b \n" // look up 4 pixels - "trn1 v4.4s, v4.4s, v5.4s \n" // combine 8 pixels - MEMACCESS(1) - "st1 {v4.8b}, [%1], #8 \n" // store 8. - "bgt 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : "r"(selector) // %3 - : "cc", "memory", "v0", "v1", "v2", "v4", "v5" // Clobber List - ); -} -#endif // HAS_ARGBTOBAYERROW_NEON - -// Select G channels from ARGB. e.g. GGGGGGGG -#ifdef HAS_ARGBTOBAYERGGROW_NEON -void ARGBToBayerGGRow_NEON(const uint8* src_argb, uint8* dst_bayer, - uint32 /*selector*/, int pix) { - asm volatile ( - "1: \n" - MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load row 8 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop - MEMACCESS(1) - "st1 {v1.8b}, [%1], #8 \n" // store 8 G's. - "bgt 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : - : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List - ); -} -#endif // HAS_ARGBTOBAYERGGROW_NEON - // For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. #ifdef HAS_ARGBSHUFFLEROW_NEON void ARGBShuffleRow_NEON(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { asm volatile ( MEMACCESS(3) "ld1 {v2.16b}, [%3] \n" // shuffler "1: \n" MEMACCESS(0) "ld1 {v0.16b}, [%0], #16 \n" // load 4 pixels. - "subs %2, %2, #4 \n" // 4 processed per loop + "subs %w2, %w2, #4 \n" // 4 processed per loop "tbl v1.16b, {v0.16b}, v2.16b \n" // look up 4 pixels MEMACCESS(1) "st1 {v1.16b}, [%1], #16 \n" // store 4. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : "r"(shuffler) // %3 : "cc", "memory", "v0", "v1", "v2" // Clobber List ); @@ -1455,19 +1231,18 @@ void I422ToYUY2Row_NEON(const uint8* src_y, const uint8* src_v, uint8* dst_yuy2, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld2 {v0.8b, v1.8b}, [%0], #16 \n" // load 16 Ys - "mov v2.8b, v1.8b \n" + "orr v2.8b, v1.8b, v1.8b \n" MEMACCESS(1) "ld1 {v1.8b}, [%1], #8 \n" // load 8 Us MEMACCESS(2) "ld1 {v3.8b}, [%2], #8 \n" // load 8 Vs - "subs %4, %4, #16 \n" // 16 pixels + "subs %w4, %w4, #16 \n" // 16 pixels MEMACCESS(3) - "st4 {v0.8b-v3.8b}, [%3], #32 \n" // Store 8 YUY2/16 pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%3], #32 \n" // Store 16 pixels. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 @@ -1485,19 +1260,18 @@ void I422ToUYVYRow_NEON(const uint8* src_y, const uint8* src_v, uint8* dst_uyvy, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld2 {v1.8b, v2.8b}, [%0], #16 \n" // load 16 Ys - "mov v3.8b, v2.8b \n" + "ld2 {v1.8b,v2.8b}, [%0], #16 \n" // load 16 Ys + "orr v3.8b, v2.8b, v2.8b \n" MEMACCESS(1) "ld1 {v0.8b}, [%1], #8 \n" // load 8 Us MEMACCESS(2) "ld1 {v2.8b}, [%2], #8 \n" // load 8 Vs - "subs %4, %4, #16 \n" // 16 pixels + "subs %w4, %w4, #16 \n" // 16 pixels MEMACCESS(3) - "st4 {v0.8b-v3.8b}, [%3], #32 \n" // Store 8 UYVY/16 pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%3], #32 \n" // Store 16 pixels. + "b.gt 1b \n" : "+r"(src_y), // %0 "+r"(src_u), // %1 "+r"(src_v), // %2 @@ -1510,83 +1284,104 @@ void I422ToUYVYRow_NEON(const uint8* src_y, #endif // HAS_I422TOUYVYROW_NEON #ifdef HAS_ARGBTORGB565ROW_NEON -void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb565, int pix) { +void ARGBToRGB565Row_NEON(const uint8* src_argb, uint8* dst_rgb565, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%0], #32 \n" // load 8 pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGBTORGB565 MEMACCESS(1) - "vst1.8 {q0}, [%1]! \n" // store 8 pixels RGB565. - "bgt 1b \n" + "st1 {v0.16b}, [%1], #16 \n" // store 8 pixels RGB565. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_rgb565), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q8", "q9", "q10", "q11" + : "cc", "memory", "v0", "v20", "v21", "v22", "v23" + ); +} +#endif // HAS_ARGBTORGB565ROW_NEON + +#ifdef HAS_ARGBTORGB565DITHERROW_NEON +void ARGBToRGB565DitherRow_NEON(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) { + asm volatile ( + "dup v1.4s, %w2 \n" // dither4 + "1: \n" + MEMACCESS(1) + "ld4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%1], #32 \n" // load 8 pixels + "subs %w3, %w3, #8 \n" // 8 processed per loop. + "uqadd v20.8b, v20.8b, v1.8b \n" + "uqadd v21.8b, v21.8b, v1.8b \n" + "uqadd v22.8b, v22.8b, v1.8b \n" + ARGBTORGB565 + MEMACCESS(0) + "st1 {v0.16b}, [%0], #16 \n" // store 8 pixels RGB565. + "b.gt 1b \n" + : "+r"(dst_rgb) // %0 + : "r"(src_argb), // %1 + "r"(dither4), // %2 + "r"(width) // %3 + : "cc", "memory", "v0", "v1", "v20", "v21", "v22", "v23" ); } #endif // HAS_ARGBTORGB565ROW_NEON #ifdef HAS_ARGBTOARGB1555ROW_NEON void ARGBToARGB1555Row_NEON(const uint8* src_argb, uint8* dst_argb1555, - int pix) { + int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%0], #32 \n" // load 8 pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGBTOARGB1555 MEMACCESS(1) - "vst1.8 {q0}, [%1]! \n" // store 8 pixels ARGB1555. - "bgt 1b \n" + "st1 {v0.16b}, [%1], #16 \n" // store 8 pixels ARGB1555. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb1555), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q8", "q9", "q10", "q11" + : "cc", "memory", "v0", "v20", "v21", "v22", "v23" ); } #endif // HAS_ARGBTOARGB1555ROW_NEON #ifdef HAS_ARGBTOARGB4444ROW_NEON void ARGBToARGB4444Row_NEON(const uint8* src_argb, uint8* dst_argb4444, - int pix) { + int width) { asm volatile ( - "vmov.u8 d4, #0x0f \n" // bits to clear with vbic. - ".p2align 2 \n" + "movi v4.16b, #0x0f \n" // bits to clear with vbic. "1: \n" MEMACCESS(0) - "vld4.8 {d20, d21, d22, d23}, [%0]! \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v20.8b,v21.8b,v22.8b,v23.8b}, [%0], #32 \n" // load 8 pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGBTOARGB4444 MEMACCESS(1) - "vst1.8 {q0}, [%1]! \n" // store 8 pixels ARGB4444. - "bgt 1b \n" + "st1 {v0.16b}, [%1], #16 \n" // store 8 pixels ARGB4444. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb4444), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q8", "q9", "q10", "q11" + : "cc", "memory", "v0", "v1", "v4", "v20", "v21", "v22", "v23" ); } #endif // HAS_ARGBTOARGB4444ROW_NEON #ifdef HAS_ARGBTOYROW_NEON -void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { +void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #13 \n" // B * 0.1016 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #33 \n" // R * 0.2578 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v3.8h, v0.8b, v4.8b \n" // B "umlal v3.8h, v1.8b, v5.8b \n" // G "umlal v3.8h, v2.8b, v6.8b \n" // R @@ -1594,10 +1389,10 @@ void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7" ); @@ -1605,26 +1400,25 @@ void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { #endif // HAS_ARGBTOYROW_NEON #ifdef HAS_ARGBTOYJROW_NEON -void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { +void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #15 \n" // B * 0.11400 coefficient "movi v5.8b, #75 \n" // G * 0.58700 coefficient "movi v6.8b, #38 \n" // R * 0.29900 coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v3.8h, v0.8b, v4.8b \n" // B "umlal v3.8h, v1.8b, v5.8b \n" // G "umlal v3.8h, v2.8b, v6.8b \n" // R "sqrshrun v0.8b, v3.8h, #7 \n" // 15 bit to 8 bit Y MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6" ); @@ -1634,7 +1428,7 @@ void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { // 8x1 pixels. #ifdef HAS_ARGBTOUV444ROW_NEON void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( "movi v24.8b, #112 \n" // UB / VR 0.875 coefficient "movi v25.8b, #74 \n" // UG -0.5781 coefficient @@ -1642,11 +1436,10 @@ void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "movi v27.8b, #18 \n" // VB -0.1406 coefficient "movi v28.8b, #94 \n" // VG -0.7344 coefficient "movi v29.16b,#0x80 \n" // 128.5 - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "umull v4.8h, v0.8b, v24.8b \n" // B "umlsl v4.8h, v1.8b, v25.8b \n" // G "umlsl v4.8h, v2.8b, v26.8b \n" // R @@ -1664,11 +1457,11 @@ void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels U. MEMACCESS(2) "st1 {v1.8b}, [%2], #8 \n" // store 8 pixels V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v24", "v25", "v26", "v27", "v28", "v29" @@ -1676,27 +1469,29 @@ void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, } #endif // HAS_ARGBTOUV444ROW_NEON -// 16x1 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +#define RGBTOUV_SETUP_REG \ + "movi v20.8h, #56, lsl #0 \n" /* UB/VR coefficient (0.875) / 2 */ \ + "movi v21.8h, #37, lsl #0 \n" /* UG coefficient (-0.5781) / 2 */ \ + "movi v22.8h, #19, lsl #0 \n" /* UR coefficient (-0.2969) / 2 */ \ + "movi v23.8h, #9, lsl #0 \n" /* VB coefficient (-0.1406) / 2 */ \ + "movi v24.8h, #47, lsl #0 \n" /* VG coefficient (-0.7344) / 2 */ \ + "movi v25.16b, #0x80 \n" /* 128.5 (0x8080 in 16-bit) */ + +// 16x1 pixels -> 8x1. width is number of argb pixels. e.g. 16. #ifdef HAS_ARGBTOUV422ROW_NEON void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - "movi v20.8h, #112 / 2 \n" // UB / VR 0.875 coefficient - "movi v21.8h, #74 / 2 \n" // UG -0.5781 coefficient - "movi v22.8h, #38 / 2 \n" // UR -0.2969 coefficient - "movi v23.8h, #18 / 2 \n" // VB -0.1406 coefficient - "movi v24.8h, #94 / 2 \n" // VG -0.7344 coefficient - "movi v25.16b, #0x80 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "ld4 {v0.16b-v3.16b}, [%0], #64 \n" // load 16 ARGB pixels. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. - "subs %3, %3, #16 \n" // 16 processed per loop. + "subs %w3, %w3, #16 \n" // 16 processed per loop. "mul v3.8h, v0.8h, v20.8h \n" // B "mls v3.8h, v1.8h, v21.8h \n" // G "mls v3.8h, v2.8h, v22.8h \n" // R @@ -1714,11 +1509,11 @@ void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels U. MEMACCESS(2) "st1 {v1.8b}, [%2], #8 \n" // store 8 pixels V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", "v21", "v22", "v23", "v24", "v25" @@ -1726,26 +1521,20 @@ void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, } #endif // HAS_ARGBTOUV422ROW_NEON -// 32x1 pixels -> 8x1. pix is number of argb pixels. e.g. 32. +// 32x1 pixels -> 8x1. width is number of argb pixels. e.g. 32. #ifdef HAS_ARGBTOUV411ROW_NEON void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int pix) { + int width) { asm volatile ( - "movi v20.8h, #112 / 2 \n" // UB / VR 0.875 coefficient - "movi v21.8h, #74 / 2 \n" // UG -0.5781 coefficient - "movi v22.8h, #38 / 2 \n" // UR -0.2969 coefficient - "movi v23.8h, #18 / 2 \n" // VB -0.1406 coefficient - "movi v24.8h, #94 / 2 \n" // VG -0.7344 coefficient - "movi v25.16b, #0x80 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "ld4 {v0.16b-v3.16b}, [%0], #64 \n" // load 16 ARGB pixels. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(0) - "ld4 {v4.16b-v7.16b}, [%0], #64 \n" // load next 16 ARGB pixels. + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%0], #64 \n" // load next 16. "uaddlp v4.8h, v4.16b \n" // B 16 bytes -> 8 shorts. "uaddlp v5.8h, v5.16b \n" // G 16 bytes -> 8 shorts. "uaddlp v6.8h, v6.16b \n" // R 16 bytes -> 8 shorts. @@ -1758,7 +1547,7 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "urshr v1.8h, v1.8h, #1 \n" "urshr v2.8h, v2.8h, #1 \n" - "subs %3, %3, #32 \n" // 32 processed per loop. + "subs %w3, %w3, #32 \n" // 32 processed per loop. "mul v3.8h, v0.8h, v20.8h \n" // B "mls v3.8h, v1.8h, v21.8h \n" // G "mls v3.8h, v2.8h, v22.8h \n" // R @@ -1773,11 +1562,11 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels U. MEMACCESS(2) "st1 {v1.8b}, [%2], #8 \n" // store 8 pixels V. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_u), // %1 "+r"(dst_v), // %2 - "+r"(pix) // %3 + "+r"(width) // %3 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", "v21", "v22", "v23", "v24", "v25" @@ -1785,67 +1574,60 @@ void ARGBToUV411Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, } #endif // HAS_ARGBTOUV411ROW_NEON -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. #define RGBTOUV(QB, QG, QR) \ - "vmul.s16 q8, " #QB ", q10 \n" /* B */ \ - "vmls.s16 q8, " #QG ", q11 \n" /* G */ \ - "vmls.s16 q8, " #QR ", q12 \n" /* R */ \ - "vadd.u16 q8, q8, q15 \n" /* +128 -> unsigned */ \ - "vmul.s16 q9, " #QR ", q10 \n" /* R */ \ - "vmls.s16 q9, " #QG ", q14 \n" /* G */ \ - "vmls.s16 q9, " #QB ", q13 \n" /* B */ \ - "vadd.u16 q9, q9, q15 \n" /* +128 -> unsigned */ \ - "vqshrn.u16 d0, q8, #8 \n" /* 16 bit to 8 bit U */ \ - "vqshrn.u16 d1, q9, #8 \n" /* 16 bit to 8 bit V */ + "mul v3.8h, " #QB ",v20.8h \n" /* B */ \ + "mul v4.8h, " #QR ",v20.8h \n" /* R */ \ + "mls v3.8h, " #QG ",v21.8h \n" /* G */ \ + "mls v4.8h, " #QG ",v24.8h \n" /* G */ \ + "mls v3.8h, " #QR ",v22.8h \n" /* R */ \ + "mls v4.8h, " #QB ",v23.8h \n" /* B */ \ + "add v3.8h, v3.8h, v25.8h \n" /* +128 -> unsigned */ \ + "add v4.8h, v4.8h, v25.8h \n" /* +128 -> unsigned */ \ + "uqshrn v0.8b, v3.8h, #8 \n" /* 16 bit to 8 bit U */ \ + "uqshrn v1.8b, v4.8h, #8 \n" /* 16 bit to 8 bit V */ // TODO(fbarchard): Consider vhadd vertical, then vpaddl horizontal, avoid shr. +// TODO(fbarchard): consider ptrdiff_t for all strides. + #ifdef HAS_ARGBTOUVROW_NEON void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_argb_1 = src_argb + src_stride_argb; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_argb - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. - MEMACCESS(0) - "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 ARGB pixels. - "vpaddl.u8 q0, q0 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q2, q2 \n" // R 16 bytes -> 8 shorts. - MEMACCESS(1) - "vld4.8 {d8, d10, d12, d14}, [%1]! \n" // load 8 more ARGB pixels. - MEMACCESS(1) - "vld4.8 {d9, d11, d13, d15}, [%1]! \n" // load last 8 ARGB pixels. - "vpadal.u8 q0, q4 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q2, q6 \n" // R 16 bytes -> 8 shorts. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. + "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + MEMACCESS(1) + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%1], #64 \n" // load next 16 + "uadalp v0.8h, v4.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v1.8h, v5.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v2.8h, v6.16b \n" // R 16 bytes -> 8 shorts. - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q0, q1, q2) + "urshr v0.8h, v0.8h, #1 \n" // 2x average + "urshr v1.8h, v1.8h, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" + + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v1.8h, v2.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_argb), // %0 - "+r"(src_stride_argb), // %1 + "+r"(src_argb_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_ARGBTOUVROW_NEON @@ -1853,628 +1635,573 @@ void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, // TODO(fbarchard): Subsample match C code. #ifdef HAS_ARGBTOUVJROW_NEON void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_argb_1 = src_argb + src_stride_argb; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_argb - "vmov.s16 q10, #127 / 2 \n" // UB / VR 0.500 coefficient - "vmov.s16 q11, #84 / 2 \n" // UG -0.33126 coefficient - "vmov.s16 q12, #43 / 2 \n" // UR -0.16874 coefficient - "vmov.s16 q13, #20 / 2 \n" // VB -0.08131 coefficient - "vmov.s16 q14, #107 / 2 \n" // VG -0.41869 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + "movi v20.8h, #63, lsl #0 \n" // UB/VR coeff (0.500) / 2 + "movi v21.8h, #42, lsl #0 \n" // UG coeff (-0.33126) / 2 + "movi v22.8h, #21, lsl #0 \n" // UR coeff (-0.16874) / 2 + "movi v23.8h, #10, lsl #0 \n" // VB coeff (-0.08131) / 2 + "movi v24.8h, #53, lsl #0 \n" // VG coeff (-0.41869) / 2 + "movi v25.16b, #0x80 \n" // 128.5 (0x8080 in 16-bit) "1: \n" MEMACCESS(0) - "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. - MEMACCESS(0) - "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 ARGB pixels. - "vpaddl.u8 q0, q0 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q2, q2 \n" // R 16 bytes -> 8 shorts. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. + "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld4.8 {d8, d10, d12, d14}, [%1]! \n" // load 8 more ARGB pixels. - MEMACCESS(1) - "vld4.8 {d9, d11, d13, d15}, [%1]! \n" // load last 8 ARGB pixels. - "vpadal.u8 q0, q4 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q2, q6 \n" // R 16 bytes -> 8 shorts. + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%1], #64 \n" // load next 16 + "uadalp v0.8h, v4.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v1.8h, v5.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v2.8h, v6.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + "urshr v0.8h, v0.8h, #1 \n" // 2x average + "urshr v1.8h, v1.8h, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q0, q1, q2) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v1.8h, v2.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_argb), // %0 - "+r"(src_stride_argb), // %1 + "+r"(src_argb_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_ARGBTOUVJROW_NEON #ifdef HAS_BGRATOUVROW_NEON void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_bgra_1 = src_bgra + src_stride_bgra; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_bgra - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 BGRA pixels. - MEMACCESS(0) - "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 BGRA pixels. - "vpaddl.u8 q3, q3 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q2, q2 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // R 16 bytes -> 8 shorts. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. + "uaddlp v0.8h, v3.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v3.8h, v2.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v1.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld4.8 {d8, d10, d12, d14}, [%1]! \n" // load 8 more BGRA pixels. - MEMACCESS(1) - "vld4.8 {d9, d11, d13, d15}, [%1]! \n" // load last 8 BGRA pixels. - "vpadal.u8 q3, q7 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q2, q6 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // R 16 bytes -> 8 shorts. + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%1], #64 \n" // load 16 more + "uadalp v0.8h, v7.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v3.8h, v6.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v2.8h, v5.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q1, q1, #1 \n" // 2x average - "vrshr.u16 q2, q2, #1 \n" - "vrshr.u16 q3, q3, #1 \n" + "urshr v0.8h, v0.8h, #1 \n" // 2x average + "urshr v1.8h, v3.8h, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q3, q2, q1) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v1.8h, v2.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_bgra), // %0 - "+r"(src_stride_bgra), // %1 + "+r"(src_bgra_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_BGRATOUVROW_NEON #ifdef HAS_ABGRTOUVROW_NEON void ABGRToUVRow_NEON(const uint8* src_abgr, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_abgr_1 = src_abgr + src_stride_abgr; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_abgr - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ABGR pixels. - MEMACCESS(0) - "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 ABGR pixels. - "vpaddl.u8 q2, q2 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q0, q0 \n" // R 16 bytes -> 8 shorts. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. + "uaddlp v3.8h, v2.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v2.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v1.8h, v0.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld4.8 {d8, d10, d12, d14}, [%1]! \n" // load 8 more ABGR pixels. - MEMACCESS(1) - "vld4.8 {d9, d11, d13, d15}, [%1]! \n" // load last 8 ABGR pixels. - "vpadal.u8 q2, q6 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q0, q4 \n" // R 16 bytes -> 8 shorts. + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%1], #64 \n" // load 16 more. + "uadalp v3.8h, v6.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v2.8h, v5.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v1.8h, v4.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + "urshr v0.8h, v3.8h, #1 \n" // 2x average + "urshr v2.8h, v2.8h, #1 \n" + "urshr v1.8h, v1.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q2, q1, q0) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v2.8h, v1.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_abgr), // %0 - "+r"(src_stride_abgr), // %1 + "+r"(src_abgr_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_ABGRTOUVROW_NEON #ifdef HAS_RGBATOUVROW_NEON void RGBAToUVRow_NEON(const uint8* src_rgba, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_rgba_1 = src_rgba + src_stride_rgba; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_rgba - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 RGBA pixels. - MEMACCESS(0) - "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 RGBA pixels. - "vpaddl.u8 q0, q1 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q2 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q2, q3 \n" // R 16 bytes -> 8 shorts. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 16 pixels. + "uaddlp v0.8h, v1.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v2.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v3.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld4.8 {d8, d10, d12, d14}, [%1]! \n" // load 8 more RGBA pixels. - MEMACCESS(1) - "vld4.8 {d9, d11, d13, d15}, [%1]! \n" // load last 8 RGBA pixels. - "vpadal.u8 q0, q5 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q6 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q2, q7 \n" // R 16 bytes -> 8 shorts. + "ld4 {v4.16b,v5.16b,v6.16b,v7.16b}, [%1], #64 \n" // load 16 more. + "uadalp v0.8h, v5.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v1.8h, v6.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v2.8h, v7.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + "urshr v0.8h, v0.8h, #1 \n" // 2x average + "urshr v1.8h, v1.8h, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q0, q1, q2) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v1.8h, v2.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_rgba), // %0 - "+r"(src_stride_rgba), // %1 + "+r"(src_rgba_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_RGBATOUVROW_NEON #ifdef HAS_RGB24TOUVROW_NEON void RGB24ToUVRow_NEON(const uint8* src_rgb24, int src_stride_rgb24, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_rgb24_1 = src_rgb24 + src_stride_rgb24; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_rgb24 - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld3.8 {d0, d2, d4}, [%0]! \n" // load 8 RGB24 pixels. - MEMACCESS(0) - "vld3.8 {d1, d3, d5}, [%0]! \n" // load next 8 RGB24 pixels. - "vpaddl.u8 q0, q0 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q2, q2 \n" // R 16 bytes -> 8 shorts. + "ld3 {v0.16b,v1.16b,v2.16b}, [%0], #48 \n" // load 16 pixels. + "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld3.8 {d8, d10, d12}, [%1]! \n" // load 8 more RGB24 pixels. - MEMACCESS(1) - "vld3.8 {d9, d11, d13}, [%1]! \n" // load last 8 RGB24 pixels. - "vpadal.u8 q0, q4 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q2, q6 \n" // R 16 bytes -> 8 shorts. + "ld3 {v4.16b,v5.16b,v6.16b}, [%1], #48 \n" // load 16 more. + "uadalp v0.8h, v4.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v1.8h, v5.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v2.8h, v6.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + "urshr v0.8h, v0.8h, #1 \n" // 2x average + "urshr v1.8h, v1.8h, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q0, q1, q2) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v0.8h, v1.8h, v2.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_rgb24), // %0 - "+r"(src_stride_rgb24), // %1 + "+r"(src_rgb24_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_RGB24TOUVROW_NEON #ifdef HAS_RAWTOUVROW_NEON void RAWToUVRow_NEON(const uint8* src_raw, int src_stride_raw, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_raw_1 = src_raw + src_stride_raw; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_raw - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld3.8 {d0, d2, d4}, [%0]! \n" // load 8 RAW pixels. - MEMACCESS(0) - "vld3.8 {d1, d3, d5}, [%0]! \n" // load next 8 RAW pixels. - "vpaddl.u8 q2, q2 \n" // B 16 bytes -> 8 shorts. - "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. - "vpaddl.u8 q0, q0 \n" // R 16 bytes -> 8 shorts. + "ld3 {v0.16b,v1.16b,v2.16b}, [%0], #48 \n" // load 8 RAW pixels. + "uaddlp v2.8h, v2.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v0.8h, v0.16b \n" // R 16 bytes -> 8 shorts. MEMACCESS(1) - "vld3.8 {d8, d10, d12}, [%1]! \n" // load 8 more RAW pixels. - MEMACCESS(1) - "vld3.8 {d9, d11, d13}, [%1]! \n" // load last 8 RAW pixels. - "vpadal.u8 q2, q6 \n" // B 16 bytes -> 8 shorts. - "vpadal.u8 q1, q5 \n" // G 16 bytes -> 8 shorts. - "vpadal.u8 q0, q4 \n" // R 16 bytes -> 8 shorts. + "ld3 {v4.16b,v5.16b,v6.16b}, [%1], #48 \n" // load 8 more RAW pixels + "uadalp v2.8h, v6.16b \n" // B 16 bytes -> 8 shorts. + "uadalp v1.8h, v5.16b \n" // G 16 bytes -> 8 shorts. + "uadalp v0.8h, v4.16b \n" // R 16 bytes -> 8 shorts. - "vrshr.u16 q0, q0, #1 \n" // 2x average - "vrshr.u16 q1, q1, #1 \n" - "vrshr.u16 q2, q2, #1 \n" + "urshr v2.8h, v2.8h, #1 \n" // 2x average + "urshr v1.8h, v1.8h, #1 \n" + "urshr v0.8h, v0.8h, #1 \n" - "subs %4, %4, #16 \n" // 32 processed per loop. - RGBTOUV(q2, q1, q0) + "subs %w4, %w4, #16 \n" // 32 processed per loop. + RGBTOUV(v2.8h, v1.8h, v0.8h) MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_raw), // %0 - "+r"(src_stride_raw), // %1 + "+r"(src_raw_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v20", "v21", "v22", "v23", "v24", "v25" ); } #endif // HAS_RAWTOUVROW_NEON -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. #ifdef HAS_RGB565TOUVROW_NEON void RGB565ToUVRow_NEON(const uint8* src_rgb565, int src_stride_rgb565, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_rgb565_1 = src_rgb565 + src_stride_rgb565; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_argb - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + "movi v22.8h, #56, lsl #0 \n" // UB / VR coeff (0.875) / 2 + "movi v23.8h, #37, lsl #0 \n" // UG coeff (-0.5781) / 2 + "movi v24.8h, #19, lsl #0 \n" // UR coeff (-0.2969) / 2 + "movi v25.8h, #9 , lsl #0 \n" // VB coeff (-0.1406) / 2 + "movi v26.8h, #47, lsl #0 \n" // VG coeff (-0.7344) / 2 + "movi v27.16b, #0x80 \n" // 128.5 (0x8080 in 16-bit) "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 RGB565 pixels. RGB565TOARGB - "vpaddl.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v18.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v20.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // next 8 RGB565 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // next 8 RGB565 pixels. RGB565TOARGB - "vpaddl.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v17.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v19.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v21.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // load 8 RGB565 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // load 8 RGB565 pixels. RGB565TOARGB - "vpadal.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v18.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v20.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // next 8 RGB565 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // next 8 RGB565 pixels. RGB565TOARGB - "vpadal.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v17.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v19.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v21.4h, v2.8b \n" // R 8 bytes -> 4 shorts. - "vrshr.u16 q4, q4, #1 \n" // 2x average - "vrshr.u16 q5, q5, #1 \n" - "vrshr.u16 q6, q6, #1 \n" + "ins v16.D[1], v17.D[0] \n" + "ins v18.D[1], v19.D[0] \n" + "ins v20.D[1], v21.D[0] \n" - "subs %4, %4, #16 \n" // 16 processed per loop. - "vmul.s16 q8, q4, q10 \n" // B - "vmls.s16 q8, q5, q11 \n" // G - "vmls.s16 q8, q6, q12 \n" // R - "vadd.u16 q8, q8, q15 \n" // +128 -> unsigned - "vmul.s16 q9, q6, q10 \n" // R - "vmls.s16 q9, q5, q14 \n" // G - "vmls.s16 q9, q4, q13 \n" // B - "vadd.u16 q9, q9, q15 \n" // +128 -> unsigned - "vqshrn.u16 d0, q8, #8 \n" // 16 bit to 8 bit U - "vqshrn.u16 d1, q9, #8 \n" // 16 bit to 8 bit V + "urshr v4.8h, v16.8h, #1 \n" // 2x average + "urshr v5.8h, v18.8h, #1 \n" + "urshr v6.8h, v20.8h, #1 \n" + + "subs %w4, %w4, #16 \n" // 16 processed per loop. + "mul v16.8h, v4.8h, v22.8h \n" // B + "mls v16.8h, v5.8h, v23.8h \n" // G + "mls v16.8h, v6.8h, v24.8h \n" // R + "add v16.8h, v16.8h, v27.8h \n" // +128 -> unsigned + "mul v17.8h, v6.8h, v22.8h \n" // R + "mls v17.8h, v5.8h, v26.8h \n" // G + "mls v17.8h, v4.8h, v25.8h \n" // B + "add v17.8h, v17.8h, v27.8h \n" // +128 -> unsigned + "uqshrn v0.8b, v16.8h, #8 \n" // 16 bit to 8 bit U + "uqshrn v1.8b, v17.8h, #8 \n" // 16 bit to 8 bit V MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_rgb565), // %0 - "+r"(src_stride_rgb565), // %1 + "+r"(src_rgb565_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", + "v25", "v26", "v27" ); } #endif // HAS_RGB565TOUVROW_NEON -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. #ifdef HAS_ARGB1555TOUVROW_NEON void ARGB1555ToUVRow_NEON(const uint8* src_argb1555, int src_stride_argb1555, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_argb1555_1 = src_argb1555 + src_stride_argb1555; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_argb - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB1555 pixels. RGB555TOARGB - "vpaddl.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v17.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v18.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // next 8 ARGB1555 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // next 8 ARGB1555 pixels. RGB555TOARGB - "vpaddl.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v26.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v27.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v28.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // load 8 ARGB1555 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // load 8 ARGB1555 pixels. RGB555TOARGB - "vpadal.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v17.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v18.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // next 8 ARGB1555 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // next 8 ARGB1555 pixels. RGB555TOARGB - "vpadal.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v26.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v27.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v28.4h, v2.8b \n" // R 8 bytes -> 4 shorts. - "vrshr.u16 q4, q4, #1 \n" // 2x average - "vrshr.u16 q5, q5, #1 \n" - "vrshr.u16 q6, q6, #1 \n" + "ins v16.D[1], v26.D[0] \n" + "ins v17.D[1], v27.D[0] \n" + "ins v18.D[1], v28.D[0] \n" - "subs %4, %4, #16 \n" // 16 processed per loop. - "vmul.s16 q8, q4, q10 \n" // B - "vmls.s16 q8, q5, q11 \n" // G - "vmls.s16 q8, q6, q12 \n" // R - "vadd.u16 q8, q8, q15 \n" // +128 -> unsigned - "vmul.s16 q9, q6, q10 \n" // R - "vmls.s16 q9, q5, q14 \n" // G - "vmls.s16 q9, q4, q13 \n" // B - "vadd.u16 q9, q9, q15 \n" // +128 -> unsigned - "vqshrn.u16 d0, q8, #8 \n" // 16 bit to 8 bit U - "vqshrn.u16 d1, q9, #8 \n" // 16 bit to 8 bit V + "urshr v4.8h, v16.8h, #1 \n" // 2x average + "urshr v5.8h, v17.8h, #1 \n" + "urshr v6.8h, v18.8h, #1 \n" + + "subs %w4, %w4, #16 \n" // 16 processed per loop. + "mul v2.8h, v4.8h, v20.8h \n" // B + "mls v2.8h, v5.8h, v21.8h \n" // G + "mls v2.8h, v6.8h, v22.8h \n" // R + "add v2.8h, v2.8h, v25.8h \n" // +128 -> unsigned + "mul v3.8h, v6.8h, v20.8h \n" // R + "mls v3.8h, v5.8h, v24.8h \n" // G + "mls v3.8h, v4.8h, v23.8h \n" // B + "add v3.8h, v3.8h, v25.8h \n" // +128 -> unsigned + "uqshrn v0.8b, v2.8h, #8 \n" // 16 bit to 8 bit U + "uqshrn v1.8b, v3.8h, #8 \n" // 16 bit to 8 bit V MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_argb1555), // %0 - "+r"(src_stride_argb1555), // %1 + "+r"(src_argb1555_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", + "v26", "v27", "v28" ); } #endif // HAS_ARGB1555TOUVROW_NEON -// 16x2 pixels -> 8x1. pix is number of argb pixels. e.g. 16. +// 16x2 pixels -> 8x1. width is number of argb pixels. e.g. 16. #ifdef HAS_ARGB4444TOUVROW_NEON void ARGB4444ToUVRow_NEON(const uint8* src_argb4444, int src_stride_argb4444, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { + const uint8* src_argb4444_1 = src_argb4444 + src_stride_argb4444; asm volatile ( - "add %1, %0, %1 \n" // src_stride + src_argb - "vmov.s16 q10, #112 / 2 \n" // UB / VR 0.875 coefficient - "vmov.s16 q11, #74 / 2 \n" // UG -0.5781 coefficient - "vmov.s16 q12, #38 / 2 \n" // UR -0.2969 coefficient - "vmov.s16 q13, #18 / 2 \n" // VB -0.1406 coefficient - "vmov.s16 q14, #94 / 2 \n" // VG -0.7344 coefficient - "vmov.u16 q15, #0x8080 \n" // 128.5 - ".p2align 2 \n" + RGBTOUV_SETUP_REG "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB4444 pixels. ARGB4444TOARGB - "vpaddl.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v17.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v18.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // next 8 ARGB4444 pixels. + "ld1 {v0.16b}, [%0], #16 \n" // next 8 ARGB4444 pixels. ARGB4444TOARGB - "vpaddl.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpaddl.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpaddl.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uaddlp v26.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uaddlp v27.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uaddlp v28.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // load 8 ARGB4444 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // load 8 ARGB4444 pixels. ARGB4444TOARGB - "vpadal.u8 d8, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d10, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d12, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v16.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v17.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v18.4h, v2.8b \n" // R 8 bytes -> 4 shorts. MEMACCESS(1) - "vld1.8 {q0}, [%1]! \n" // next 8 ARGB4444 pixels. + "ld1 {v0.16b}, [%1], #16 \n" // next 8 ARGB4444 pixels. ARGB4444TOARGB - "vpadal.u8 d9, d0 \n" // B 8 bytes -> 4 shorts. - "vpadal.u8 d11, d1 \n" // G 8 bytes -> 4 shorts. - "vpadal.u8 d13, d2 \n" // R 8 bytes -> 4 shorts. + "uadalp v26.4h, v0.8b \n" // B 8 bytes -> 4 shorts. + "uadalp v27.4h, v1.8b \n" // G 8 bytes -> 4 shorts. + "uadalp v28.4h, v2.8b \n" // R 8 bytes -> 4 shorts. - "vrshr.u16 q4, q4, #1 \n" // 2x average - "vrshr.u16 q5, q5, #1 \n" - "vrshr.u16 q6, q6, #1 \n" + "ins v16.D[1], v26.D[0] \n" + "ins v17.D[1], v27.D[0] \n" + "ins v18.D[1], v28.D[0] \n" - "subs %4, %4, #16 \n" // 16 processed per loop. - "vmul.s16 q8, q4, q10 \n" // B - "vmls.s16 q8, q5, q11 \n" // G - "vmls.s16 q8, q6, q12 \n" // R - "vadd.u16 q8, q8, q15 \n" // +128 -> unsigned - "vmul.s16 q9, q6, q10 \n" // R - "vmls.s16 q9, q5, q14 \n" // G - "vmls.s16 q9, q4, q13 \n" // B - "vadd.u16 q9, q9, q15 \n" // +128 -> unsigned - "vqshrn.u16 d0, q8, #8 \n" // 16 bit to 8 bit U - "vqshrn.u16 d1, q9, #8 \n" // 16 bit to 8 bit V + "urshr v4.8h, v16.8h, #1 \n" // 2x average + "urshr v5.8h, v17.8h, #1 \n" + "urshr v6.8h, v18.8h, #1 \n" + + "subs %w4, %w4, #16 \n" // 16 processed per loop. + "mul v2.8h, v4.8h, v20.8h \n" // B + "mls v2.8h, v5.8h, v21.8h \n" // G + "mls v2.8h, v6.8h, v22.8h \n" // R + "add v2.8h, v2.8h, v25.8h \n" // +128 -> unsigned + "mul v3.8h, v6.8h, v20.8h \n" // R + "mls v3.8h, v5.8h, v24.8h \n" // G + "mls v3.8h, v4.8h, v23.8h \n" // B + "add v3.8h, v3.8h, v25.8h \n" // +128 -> unsigned + "uqshrn v0.8b, v2.8h, #8 \n" // 16 bit to 8 bit U + "uqshrn v1.8b, v3.8h, #8 \n" // 16 bit to 8 bit V MEMACCESS(2) - "vst1.8 {d0}, [%2]! \n" // store 8 pixels U. + "st1 {v0.8b}, [%2], #8 \n" // store 8 pixels U. MEMACCESS(3) - "vst1.8 {d1}, [%3]! \n" // store 8 pixels V. - "bgt 1b \n" + "st1 {v1.8b}, [%3], #8 \n" // store 8 pixels V. + "b.gt 1b \n" : "+r"(src_argb4444), // %0 - "+r"(src_stride_argb4444), // %1 + "+r"(src_argb4444_1), // %1 "+r"(dst_u), // %2 "+r"(dst_v), // %3 - "+r"(pix) // %4 + "+r"(width) // %4 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", + "v26", "v27", "v28" + ); } #endif // HAS_ARGB4444TOUVROW_NEON #ifdef HAS_RGB565TOYROW_NEON -void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int pix) { +void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int width) { asm volatile ( - "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient - "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient - "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient - "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" + "movi v24.8b, #13 \n" // B * 0.1016 coefficient + "movi v25.8b, #65 \n" // G * 0.5078 coefficient + "movi v26.8b, #33 \n" // R * 0.2578 coefficient + "movi v27.8b, #16 \n" // Add 16 constant "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 RGB565 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 RGB565 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. RGB565TOARGB - "vmull.u8 q2, d0, d24 \n" // B - "vmlal.u8 q2, d1, d25 \n" // G - "vmlal.u8 q2, d2, d26 \n" // R - "vqrshrun.s16 d0, q2, #7 \n" // 16 bit to 8 bit Y - "vqadd.u8 d0, d27 \n" + "umull v3.8h, v0.8b, v24.8b \n" // B + "umlal v3.8h, v1.8b, v25.8b \n" // G + "umlal v3.8h, v2.8b, v26.8b \n" // R + "sqrshrun v0.8b, v3.8h, #7 \n" // 16 bit to 8 bit Y + "uqadd v0.8b, v0.8b, v27.8b \n" MEMACCESS(1) - "vst1.8 {d0}, [%1]! \n" // store 8 pixels Y. - "bgt 1b \n" + "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. + "b.gt 1b \n" : "+r"(src_rgb565), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v6", + "v24", "v25", "v26", "v27" ); } #endif // HAS_RGB565TOYROW_NEON #ifdef HAS_ARGB1555TOYROW_NEON -void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int pix) { +void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int width) { asm volatile ( - "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient - "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient - "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient - "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" + "movi v4.8b, #13 \n" // B * 0.1016 coefficient + "movi v5.8b, #65 \n" // G * 0.5078 coefficient + "movi v6.8b, #33 \n" // R * 0.2578 coefficient + "movi v7.8b, #16 \n" // Add 16 constant "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB1555 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB1555 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGB1555TOARGB - "vmull.u8 q2, d0, d24 \n" // B - "vmlal.u8 q2, d1, d25 \n" // G - "vmlal.u8 q2, d2, d26 \n" // R - "vqrshrun.s16 d0, q2, #7 \n" // 16 bit to 8 bit Y - "vqadd.u8 d0, d27 \n" + "umull v3.8h, v0.8b, v4.8b \n" // B + "umlal v3.8h, v1.8b, v5.8b \n" // G + "umlal v3.8h, v2.8b, v6.8b \n" // R + "sqrshrun v0.8b, v3.8h, #7 \n" // 16 bit to 8 bit Y + "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) - "vst1.8 {d0}, [%1]! \n" // store 8 pixels Y. - "bgt 1b \n" + "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. + "b.gt 1b \n" : "+r"(src_argb1555), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7" ); } #endif // HAS_ARGB1555TOYROW_NEON #ifdef HAS_ARGB4444TOYROW_NEON -void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int pix) { +void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int width) { asm volatile ( - "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient - "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient - "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient - "vmov.u8 d27, #16 \n" // Add 16 constant - ".p2align 2 \n" + "movi v24.8b, #13 \n" // B * 0.1016 coefficient + "movi v25.8b, #65 \n" // G * 0.5078 coefficient + "movi v26.8b, #33 \n" // R * 0.2578 coefficient + "movi v27.8b, #16 \n" // Add 16 constant "1: \n" MEMACCESS(0) - "vld1.8 {q0}, [%0]! \n" // load 8 ARGB4444 pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld1 {v0.16b}, [%0], #16 \n" // load 8 ARGB4444 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. ARGB4444TOARGB - "vmull.u8 q2, d0, d24 \n" // B - "vmlal.u8 q2, d1, d25 \n" // G - "vmlal.u8 q2, d2, d26 \n" // R - "vqrshrun.s16 d0, q2, #7 \n" // 16 bit to 8 bit Y - "vqadd.u8 d0, d27 \n" + "umull v3.8h, v0.8b, v24.8b \n" // B + "umlal v3.8h, v1.8b, v25.8b \n" // G + "umlal v3.8h, v2.8b, v26.8b \n" // R + "sqrshrun v0.8b, v3.8h, #7 \n" // 16 bit to 8 bit Y + "uqadd v0.8b, v0.8b, v27.8b \n" MEMACCESS(1) - "vst1.8 {d0}, [%1]! \n" // store 8 pixels Y. - "bgt 1b \n" + "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. + "b.gt 1b \n" : "+r"(src_argb4444), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : - : "cc", "memory", "q0", "q1", "q2", "q3", "q12", "q13" + : "cc", "memory", "v0", "v1", "v2", "v3", "v24", "v25", "v26", "v27" ); } #endif // HAS_ARGB4444TOYROW_NEON #ifdef HAS_BGRATOYROW_NEON -void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix) { +void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #33 \n" // R * 0.2578 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #13 \n" // B * 0.1016 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 pixels of BGRA. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v16.8h, v1.8b, v4.8b \n" // R "umlal v16.8h, v2.8b, v5.8b \n" // G "umlal v16.8h, v3.8b, v6.8b \n" // B @@ -2482,10 +2209,10 @@ void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_bgra), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); @@ -2493,17 +2220,16 @@ void BGRAToYRow_NEON(const uint8* src_bgra, uint8* dst_y, int pix) { #endif // HAS_BGRATOYROW_NEON #ifdef HAS_ABGRTOYROW_NEON -void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix) { +void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #33 \n" // R * 0.2578 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #13 \n" // B * 0.1016 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 pixels of ABGR. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v16.8h, v0.8b, v4.8b \n" // R "umlal v16.8h, v1.8b, v5.8b \n" // G "umlal v16.8h, v2.8b, v6.8b \n" // B @@ -2511,10 +2237,10 @@ void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_abgr), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); @@ -2522,17 +2248,16 @@ void ABGRToYRow_NEON(const uint8* src_abgr, uint8* dst_y, int pix) { #endif // HAS_ABGRTOYROW_NEON #ifdef HAS_RGBATOYROW_NEON -void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix) { +void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #13 \n" // B * 0.1016 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #33 \n" // R * 0.2578 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 pixels of RGBA. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v16.8h, v1.8b, v4.8b \n" // B "umlal v16.8h, v2.8b, v5.8b \n" // G "umlal v16.8h, v3.8b, v6.8b \n" // R @@ -2540,10 +2265,10 @@ void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_rgba), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); @@ -2551,17 +2276,16 @@ void RGBAToYRow_NEON(const uint8* src_rgba, uint8* dst_y, int pix) { #endif // HAS_RGBATOYROW_NEON #ifdef HAS_RGB24TOYROW_NEON -void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix) { +void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #13 \n" // B * 0.1016 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #33 \n" // R * 0.2578 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld3 {v0.8b-v2.8b}, [%0], #24 \n" // load 8 pixels of RGB24. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld3 {v0.8b,v1.8b,v2.8b}, [%0], #24 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v16.8h, v0.8b, v4.8b \n" // B "umlal v16.8h, v1.8b, v5.8b \n" // G "umlal v16.8h, v2.8b, v6.8b \n" // R @@ -2569,10 +2293,10 @@ void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_rgb24), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); @@ -2580,17 +2304,16 @@ void RGB24ToYRow_NEON(const uint8* src_rgb24, uint8* dst_y, int pix) { #endif // HAS_RGB24TOYROW_NEON #ifdef HAS_RAWTOYROW_NEON -void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix) { +void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int width) { asm volatile ( "movi v4.8b, #33 \n" // R * 0.2578 coefficient "movi v5.8b, #65 \n" // G * 0.5078 coefficient "movi v6.8b, #13 \n" // B * 0.1016 coefficient "movi v7.8b, #16 \n" // Add 16 constant - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld3 {v0.8b-v2.8b}, [%0], #24 \n" // load 8 pixels of RAW. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld3 {v0.8b,v1.8b,v2.8b}, [%0], #24 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v16.8h, v0.8b, v4.8b \n" // B "umlal v16.8h, v1.8b, v5.8b \n" // G "umlal v16.8h, v2.8b, v6.8b \n" // R @@ -2598,10 +2321,10 @@ void RAWToYRow_NEON(const uint8* src_raw, uint8* dst_y, int pix) { "uqadd v0.8b, v0.8b, v7.8b \n" MEMACCESS(1) "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_raw), // %0 "+r"(dst_y), // %1 - "+r"(pix) // %2 + "+r"(width) // %2 : : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); @@ -2617,14 +2340,10 @@ void InterpolateRow_NEON(uint8* dst_ptr, int y0_fraction = 256 - y1_fraction; const uint8* src_ptr1 = src_ptr + src_stride; asm volatile ( - "cmp %4, #0 \n" - "beq 100f \n" - "cmp %4, #64 \n" - "beq 75f \n" - "cmp %4, #128 \n" - "beq 50f \n" - "cmp %4, #192 \n" - "beq 25f \n" + "cmp %w4, #0 \n" + "b.eq 100f \n" + "cmp %w4, #128 \n" + "b.eq 50f \n" "dup v5.16b, %w4 \n" "dup v4.16b, %w5 \n" @@ -2634,7 +2353,7 @@ void InterpolateRow_NEON(uint8* dst_ptr, "ld1 {v0.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "umull v2.8h, v0.8b, v4.8b \n" "umull2 v3.8h, v0.16b, v4.16b \n" "umlal v2.8h, v1.8b, v5.8b \n" @@ -2643,21 +2362,7 @@ void InterpolateRow_NEON(uint8* dst_ptr, "rshrn2 v0.16b, v3.8h, #8 \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 1b \n" - "b 99f \n" - - // Blend 25 / 75. - "25: \n" - MEMACCESS(1) - "ld1 {v0.16b}, [%1], #16 \n" - MEMACCESS(2) - "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" - "urhadd v0.16b, v0.16b, v1.16b \n" - "urhadd v0.16b, v0.16b, v1.16b \n" - MEMACCESS(0) - "st1 {v0.16b}, [%0], #16 \n" - "bgt 25b \n" + "b.gt 1b \n" "b 99f \n" // Blend 50 / 50. @@ -2666,35 +2371,21 @@ void InterpolateRow_NEON(uint8* dst_ptr, "ld1 {v0.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "urhadd v0.16b, v0.16b, v1.16b \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 50b \n" - "b 99f \n" - - // Blend 75 / 25. - "75: \n" - MEMACCESS(1) - "ld1 {v1.16b}, [%1], #16 \n" - MEMACCESS(2) - "ld1 {v0.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" - "urhadd v0.16b, v0.16b, v1.16b \n" - "urhadd v0.16b, v0.16b, v1.16b \n" - MEMACCESS(0) - "st1 {v0.16b}, [%0], #16 \n" - "bgt 75b \n" + "b.gt 50b \n" "b 99f \n" // Blend 100 / 0 - Copy row unchanged. "100: \n" MEMACCESS(1) "ld1 {v0.16b}, [%1], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 100b \n" + "b.gt 100b \n" "99: \n" : "+r"(dst_ptr), // %0 @@ -2714,15 +2405,15 @@ void InterpolateRow_NEON(uint8* dst_ptr, void ARGBBlendRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( - "subs %3, %3, #8 \n" - "blt 89f \n" + "subs %w3, %w3, #8 \n" + "b.lt 89f \n" // Blend 8 pixels. "8: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 pixels of ARGB0. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB0 pixels MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load 8 pixels of ARGB1. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load 8 ARGB1 pixels + "subs %w3, %w3, #8 \n" // 8 processed per loop. "umull v16.8h, v4.8b, v3.8b \n" // db * a "umull v17.8h, v5.8b, v3.8b \n" // dg * a "umull v18.8h, v6.8b, v3.8b \n" // dr * a @@ -2737,20 +2428,20 @@ void ARGBBlendRow_NEON(const uint8* src_argb0, const uint8* src_argb1, "uqadd v2.8b, v2.8b, v6.8b \n" // + sr "movi v3.8b, #255 \n" // a = 255 MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 pixels of ARGB. - "bge 8b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.ge 8b \n" "89: \n" - "adds %3, %3, #8-1 \n" - "blt 99f \n" + "adds %w3, %w3, #8-1 \n" + "b.lt 99f \n" // Blend 1 pixels. "1: \n" MEMACCESS(0) - "ld4 {v0.b-v3.b}[0], [%0], #4 \n" // load 1 pixel ARGB0. + "ld4 {v0.b,v1.b,v2.b,v3.b}[0], [%0], #4 \n" // load 1 pixel ARGB0. MEMACCESS(1) - "ld4 {v4.b-v7.b}[0], [%1], #4 \n" // load 1 pixel ARGB1. - "subs %3, %3, #1 \n" // 1 processed per loop. + "ld4 {v4.b,v5.b,v6.b,v7.b}[0], [%1], #4 \n" // load 1 pixel ARGB1. + "subs %w3, %w3, #1 \n" // 1 processed per loop. "umull v16.8h, v4.8b, v3.8b \n" // db * a "umull v17.8h, v5.8b, v3.8b \n" // dg * a "umull v18.8h, v6.8b, v3.8b \n" // dr * a @@ -2765,8 +2456,8 @@ void ARGBBlendRow_NEON(const uint8* src_argb0, const uint8* src_argb1, "uqadd v2.8b, v2.8b, v6.8b \n" // + sr "movi v3.8b, #255 \n" // a = 255 MEMACCESS(2) - "st4 {v0.b-v3.b}[0], [%2], #4 \n" // store 1 pixel. - "bge 1b \n" + "st4 {v0.b,v1.b,v2.b,v3.b}[0], [%2], #4 \n" // store 1 pixel. + "b.ge 1b \n" "99: \n" @@ -2788,8 +2479,8 @@ void ARGBAttenuateRow_NEON(const uint8* src_argb, uint8* dst_argb, int width) { // Attenuate 8 pixels. "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v4.8h, v0.8b, v3.8b \n" // b * a "umull v5.8h, v1.8b, v3.8b \n" // g * a "umull v6.8h, v2.8b, v3.8b \n" // r * a @@ -2797,8 +2488,8 @@ void ARGBAttenuateRow_NEON(const uint8* src_argb, uint8* dst_argb, int width) { "uqrshrn v1.8b, v5.8h, #8 \n" // g >>= 8 "uqrshrn v2.8b, v6.8h, #8 \n" // r >>= 8 MEMACCESS(1) - "st4 {v0.8b-v3.8b}, [%1], #32 \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 @@ -2820,11 +2511,10 @@ void ARGBQuantizeRow_NEON(uint8* dst_argb, int scale, int interval_size, "dup v6.8h, %w4 \n" // interval add // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0] \n" // load 8 pixels of ARGB. - "subs %1, %1, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0] \n" // load 8 pixels of ARGB. + "subs %w1, %w1, #8 \n" // 8 processed per loop. "uxtl v0.8h, v0.8b \n" // b (0 .. 255) "uxtl v1.8h, v1.8b \n" "uxtl v2.8h, v2.8b \n" @@ -2841,8 +2531,8 @@ void ARGBQuantizeRow_NEON(uint8* dst_argb, int scale, int interval_size, "uqxtn v1.8b, v1.8h \n" "uqxtn v2.8b, v2.8h \n" MEMACCESS(0) - "st4 {v0.8b-v3.8b}, [%0], #32 \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(dst_argb), // %0 "+r"(width) // %1 : "r"(scale), // %2 @@ -2865,11 +2555,10 @@ void ARGBShadeRow_NEON(const uint8* src_argb, uint8* dst_argb, int width, "ushr v0.8h, v0.8h, #1 \n" // scale / 2. // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v4.8b-v7.8b}, [%0], #32 \n" // load 8 pixels of ARGB. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "uxtl v4.8h, v4.8b \n" // b (0 .. 255) "uxtl v5.8h, v5.8b \n" "uxtl v6.8h, v6.8b \n" @@ -2883,8 +2572,8 @@ void ARGBShadeRow_NEON(const uint8* src_argb, uint8* dst_argb, int width, "uqxtn v6.8b, v6.8h \n" "uqxtn v7.8b, v7.8h \n" MEMACCESS(1) - "st4 {v4.8b-v7.8b}, [%1], #32 \n" // store 8 pixels of ARGB. - "bgt 1b \n" + "st4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 @@ -2903,20 +2592,19 @@ void ARGBGrayRow_NEON(const uint8* src_argb, uint8* dst_argb, int width) { "movi v24.8b, #15 \n" // B * 0.11400 coefficient "movi v25.8b, #75 \n" // G * 0.58700 coefficient "movi v26.8b, #38 \n" // R * 0.29900 coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "umull v4.8h, v0.8b, v24.8b \n" // B "umlal v4.8h, v1.8b, v25.8b \n" // G "umlal v4.8h, v2.8b, v26.8b \n" // R "sqrshrun v0.8b, v4.8h, #7 \n" // 15 bit to 8 bit B - "mov v1.8b, v0.8b \n" // G - "mov v2.8b, v0.8b \n" // R + "orr v1.8b, v0.8b, v0.8b \n" // G + "orr v2.8b, v0.8b, v0.8b \n" // R MEMACCESS(1) - "st4 {v0.8b-v3.8b}, [%1], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" // store 8 pixels. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 @@ -2943,11 +2631,10 @@ void ARGBSepiaRow_NEON(uint8* dst_argb, int width) { "movi v28.8b, #24 \n" // BB coefficient "movi v29.8b, #98 \n" // BG coefficient "movi v30.8b, #50 \n" // BR coefficient - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0] \n" // load 8 ARGB pixels. - "subs %1, %1, #8 \n" // 8 processed per loop. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0] \n" // load 8 ARGB pixels. + "subs %w1, %w1, #8 \n" // 8 processed per loop. "umull v4.8h, v0.8b, v20.8b \n" // B to Sepia B "umlal v4.8h, v1.8b, v21.8b \n" // G "umlal v4.8h, v2.8b, v22.8b \n" // R @@ -2961,8 +2648,8 @@ void ARGBSepiaRow_NEON(uint8* dst_argb, int width) { "uqshrn v1.8b, v5.8h, #7 \n" // 16 bit to 8 bit G "uqshrn v2.8b, v6.8h, #7 \n" // 16 bit to 8 bit R MEMACCESS(0) - "st4 {v0.8b-v3.8b}, [%0], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // store 8 pixels. + "b.gt 1b \n" : "+r"(dst_argb), // %0 "+r"(width) // %1 : @@ -2984,11 +2671,10 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "sxtl v0.8h, v2.8b \n" // B,G coefficients s16. "sxtl2 v1.8h, v2.16b \n" // R,A coefficients s16. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v16.8b-v19.8b}, [%0], #32 \n" // load 8 ARGB pixels. - "subs %2, %2, #8 \n" // 8 processed per loop. + "ld4 {v16.8b,v17.8b,v18.8b,v19.8b}, [%0], #32 \n" // load 8 pixels. + "subs %w2, %w2, #8 \n" // 8 processed per loop. "uxtl v16.8h, v16.8b \n" // b (0 .. 255) 16 bit "uxtl v17.8h, v17.8b \n" // g "uxtl v18.8h, v18.8b \n" // r @@ -3026,8 +2712,8 @@ void ARGBColorMatrixRow_NEON(const uint8* src_argb, uint8* dst_argb, "sqshrun v18.8b, v24.8h, #6 \n" // 16 bit to 8 bit R "sqshrun v19.8b, v25.8h, #6 \n" // 16 bit to 8 bit A MEMACCESS(1) - "st4 {v16.8b-v19.8b}, [%1], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v16.8b,v17.8b,v18.8b,v19.8b}, [%1], #32 \n" // store 8 pixels. + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 "+r"(width) // %2 @@ -3045,13 +2731,12 @@ void ARGBMultiplyRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load 8 more ARGB pixels. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load 8 more pixels. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "umull v0.8h, v0.8b, v4.8b \n" // multiply B "umull v1.8h, v1.8b, v5.8b \n" // multiply G "umull v2.8h, v2.8b, v6.8b \n" // multiply R @@ -3061,8 +2746,8 @@ void ARGBMultiplyRow_NEON(const uint8* src_argb0, const uint8* src_argb1, "rshrn v2.8b, v2.8h, #8 \n" // 16 bit to 8 bit R "rshrn v3.8b, v3.8h, #8 \n" // 16 bit to 8 bit A MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb0), // %0 "+r"(src_argb1), // %1 @@ -3080,20 +2765,19 @@ void ARGBAddRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load 8 more ARGB pixels. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load 8 more pixels. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "uqadd v0.8b, v0.8b, v4.8b \n" "uqadd v1.8b, v1.8b, v5.8b \n" "uqadd v2.8b, v2.8b, v6.8b \n" "uqadd v3.8b, v3.8b, v7.8b \n" MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb0), // %0 "+r"(src_argb1), // %1 @@ -3111,20 +2795,19 @@ void ARGBSubtractRow_NEON(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { asm volatile ( // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // load 8 ARGB pixels. MEMACCESS(1) - "ld4 {v4.8b-v7.8b}, [%1], #32 \n" // load 8 more ARGB pixels. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%1], #32 \n" // load 8 more pixels. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "uqsub v0.8b, v0.8b, v4.8b \n" "uqsub v1.8b, v1.8b, v5.8b \n" "uqsub v2.8b, v2.8b, v6.8b \n" "uqsub v3.8b, v3.8b, v7.8b \n" MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_argb0), // %0 "+r"(src_argb1), // %1 @@ -3147,19 +2830,18 @@ void SobelRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, asm volatile ( "movi v3.8b, #255 \n" // alpha // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.8b}, [%0], #8 \n" // load 8 sobelx. MEMACCESS(1) "ld1 {v1.8b}, [%1], #8 \n" // load 8 sobely. - "subs %3, %3, #8 \n" // 8 processed per loop. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "uqadd v0.8b, v0.8b, v1.8b \n" // add - "mov v1.8b, v0.8b \n" - "mov v2.8b, v0.8b \n" + "orr v1.8b, v0.8b, v0.8b \n" + "orr v2.8b, v0.8b, v0.8b \n" MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_sobelx), // %0 "+r"(src_sobely), // %1 "+r"(dst_argb), // %2 @@ -3176,17 +2858,16 @@ void SobelToPlaneRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_y, int width) { asm volatile ( // 16 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.16b}, [%0], #16 \n" // load 16 sobelx. MEMACCESS(1) "ld1 {v1.16b}, [%1], #16 \n" // load 16 sobely. - "subs %3, %3, #16 \n" // 16 processed per loop. + "subs %w3, %w3, #16 \n" // 16 processed per loop. "uqadd v0.16b, v0.16b, v1.16b \n" // add MEMACCESS(2) "st1 {v0.16b}, [%2], #16 \n" // store 16 pixels. - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_sobelx), // %0 "+r"(src_sobely), // %1 "+r"(dst_y), // %2 @@ -3208,17 +2889,16 @@ void SobelXYRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, asm volatile ( "movi v3.8b, #255 \n" // alpha // 8 pixel loop. - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v2.8b}, [%0], #8 \n" // load 8 sobelx. MEMACCESS(1) "ld1 {v0.8b}, [%1], #8 \n" // load 8 sobely. - "subs %3, %3, #8 \n" // 8 processed per loop. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "uqadd v1.8b, v0.8b, v2.8b \n" // add MEMACCESS(2) - "st4 {v0.8b-v3.8b}, [%2], #32 \n" // store 8 ARGB pixels. - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" // store 8 ARGB pixels + "b.gt 1b \n" : "+r"(src_sobelx), // %0 "+r"(src_sobely), // %1 "+r"(dst_argb), // %2 @@ -3237,7 +2917,6 @@ void SobelXYRow_NEON(const uint8* src_sobelx, const uint8* src_sobely, void SobelXRow_NEON(const uint8* src_y0, const uint8* src_y1, const uint8* src_y2, uint8* dst_sobelx, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.8b}, [%0],%5 \n" // top @@ -3255,21 +2934,21 @@ void SobelXRow_NEON(const uint8* src_y0, const uint8* src_y1, "ld1 {v2.8b}, [%2],%5 \n" // bottom MEMACCESS(2) "ld1 {v3.8b}, [%2],%6 \n" - "subs %4, %4, #8 \n" // 8 pixels + "subs %w4, %w4, #8 \n" // 8 pixels "usubl v1.8h, v2.8b, v3.8b \n" "add v0.8h, v0.8h, v1.8h \n" "abs v0.8h, v0.8h \n" "uqxtn v0.8b, v0.8h \n" MEMACCESS(3) "st1 {v0.8b}, [%3], #8 \n" // store 8 sobelx - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_y0), // %0 "+r"(src_y1), // %1 "+r"(src_y2), // %2 "+r"(dst_sobelx), // %3 "+r"(width) // %4 - : "r"(2), // %5 - "r"(6) // %6 + : "r"(2LL), // %5 + "r"(6LL) // %6 : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List ); } @@ -3283,7 +2962,6 @@ void SobelXRow_NEON(const uint8* src_y0, const uint8* src_y1, void SobelYRow_NEON(const uint8* src_y0, const uint8* src_y1, uint8* dst_sobely, int width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "ld1 {v0.8b}, [%0],%4 \n" // left @@ -3301,20 +2979,20 @@ void SobelYRow_NEON(const uint8* src_y0, const uint8* src_y1, "ld1 {v2.8b}, [%0],%5 \n" // right MEMACCESS(1) "ld1 {v3.8b}, [%1],%5 \n" - "subs %3, %3, #8 \n" // 8 pixels + "subs %w3, %w3, #8 \n" // 8 pixels "usubl v1.8h, v2.8b, v3.8b \n" "add v0.8h, v0.8h, v1.8h \n" "abs v0.8h, v0.8h \n" "uqxtn v0.8b, v0.8h \n" MEMACCESS(2) "st1 {v0.8b}, [%2], #8 \n" // store 8 sobely - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_y0), // %0 "+r"(src_y1), // %1 "+r"(dst_sobely), // %2 "+r"(width) // %3 - : "r"(1), // %4 - "r"(6) // %5 + : "r"(1LL), // %4 + "r"(6LL) // %5 : "cc", "memory", "v0", "v1", "v2", "v3" // Clobber List ); } diff --git a/TMessagesProj/jni/libyuv/source/row_posix.cc b/TMessagesProj/jni/libyuv/source/row_posix.cc deleted file mode 100644 index 106fda56..00000000 --- a/TMessagesProj/jni/libyuv/source/row_posix.cc +++ /dev/null @@ -1,6443 +0,0 @@ -/* - * Copyright 2011 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "libyuv/row.h" - -#ifdef __cplusplus -namespace libyuv { -extern "C" { -#endif - -// This module is for GCC x86 and x64. -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3) - -// Constants for ARGB -static vec8 kARGBToY = { - 13, 65, 33, 0, 13, 65, 33, 0, 13, 65, 33, 0, 13, 65, 33, 0 -}; - -// JPeg full range. -static vec8 kARGBToYJ = { - 15, 75, 38, 0, 15, 75, 38, 0, 15, 75, 38, 0, 15, 75, 38, 0 -}; -#endif // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3) - -#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3) - -static vec8 kARGBToU = { - 112, -74, -38, 0, 112, -74, -38, 0, 112, -74, -38, 0, 112, -74, -38, 0 -}; - -static vec8 kARGBToUJ = { - 127, -84, -43, 0, 127, -84, -43, 0, 127, -84, -43, 0, 127, -84, -43, 0 -}; - -static vec8 kARGBToV = { - -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112, 0, -}; - -static vec8 kARGBToVJ = { - -20, -107, 127, 0, -20, -107, 127, 0, -20, -107, 127, 0, -20, -107, 127, 0 -}; - -// Constants for BGRA -static vec8 kBGRAToY = { - 0, 33, 65, 13, 0, 33, 65, 13, 0, 33, 65, 13, 0, 33, 65, 13 -}; - -static vec8 kBGRAToU = { - 0, -38, -74, 112, 0, -38, -74, 112, 0, -38, -74, 112, 0, -38, -74, 112 -}; - -static vec8 kBGRAToV = { - 0, 112, -94, -18, 0, 112, -94, -18, 0, 112, -94, -18, 0, 112, -94, -18 -}; - -// Constants for ABGR -static vec8 kABGRToY = { - 33, 65, 13, 0, 33, 65, 13, 0, 33, 65, 13, 0, 33, 65, 13, 0 -}; - -static vec8 kABGRToU = { - -38, -74, 112, 0, -38, -74, 112, 0, -38, -74, 112, 0, -38, -74, 112, 0 -}; - -static vec8 kABGRToV = { - 112, -94, -18, 0, 112, -94, -18, 0, 112, -94, -18, 0, 112, -94, -18, 0 -}; - -// Constants for RGBA. -static vec8 kRGBAToY = { - 0, 13, 65, 33, 0, 13, 65, 33, 0, 13, 65, 33, 0, 13, 65, 33 -}; - -static vec8 kRGBAToU = { - 0, 112, -74, -38, 0, 112, -74, -38, 0, 112, -74, -38, 0, 112, -74, -38 -}; - -static vec8 kRGBAToV = { - 0, -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112 -}; - -static uvec8 kAddY16 = { - 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u -}; - -static vec16 kAddYJ64 = { - 64, 64, 64, 64, 64, 64, 64, 64 -}; - -static uvec8 kAddUV128 = { - 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, - 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u -}; - -static uvec16 kAddUVJ128 = { - 0x8080u, 0x8080u, 0x8080u, 0x8080u, 0x8080u, 0x8080u, 0x8080u, 0x8080u -}; -#endif // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3) - -#ifdef HAS_RGB24TOARGBROW_SSSE3 - -// Shuffle table for converting RGB24 to ARGB. -static uvec8 kShuffleMaskRGB24ToARGB = { - 0u, 1u, 2u, 12u, 3u, 4u, 5u, 13u, 6u, 7u, 8u, 14u, 9u, 10u, 11u, 15u -}; - -// Shuffle table for converting RAW to ARGB. -static uvec8 kShuffleMaskRAWToARGB = { - 2u, 1u, 0u, 12u, 5u, 4u, 3u, 13u, 8u, 7u, 6u, 14u, 11u, 10u, 9u, 15u -}; - -// Shuffle table for converting ARGB to RGB24. -static uvec8 kShuffleMaskARGBToRGB24 = { - 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u -}; - -// Shuffle table for converting ARGB to RAW. -static uvec8 kShuffleMaskARGBToRAW = { - 2u, 1u, 0u, 6u, 5u, 4u, 10u, 9u, 8u, 14u, 13u, 12u, 128u, 128u, 128u, 128u -}; - -// Shuffle table for converting ARGBToRGB24 for I422ToRGB24. First 8 + next 4 -static uvec8 kShuffleMaskARGBToRGB24_0 = { - 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 128u, 128u, 128u, 128u, 10u, 12u, 13u, 14u -}; - -// Shuffle table for converting ARGB to RAW. -static uvec8 kShuffleMaskARGBToRAW_0 = { - 2u, 1u, 0u, 6u, 5u, 4u, 10u, 9u, 128u, 128u, 128u, 128u, 8u, 14u, 13u, 12u -}; -#endif // HAS_RGB24TOARGBROW_SSSE3 - -#if defined(TESTING) && defined(__x86_64__) -void TestRow_SSE2(const uint8* src_y, uint8* dst_argb, int pix) { - asm volatile ( - ".p2align 5 \n" - "mov %%eax,%%eax \n" - "mov %%ebx,%%ebx \n" - "mov %%ecx,%%ecx \n" - "mov %%edx,%%edx \n" - "mov %%esi,%%esi \n" - "mov %%edi,%%edi \n" - "mov %%ebp,%%ebp \n" - "mov %%esp,%%esp \n" - ".p2align 5 \n" - "mov %%r8d,%%r8d \n" - "mov %%r9d,%%r9d \n" - "mov %%r10d,%%r10d \n" - "mov %%r11d,%%r11d \n" - "mov %%r12d,%%r12d \n" - "mov %%r13d,%%r13d \n" - "mov %%r14d,%%r14d \n" - "mov %%r15d,%%r15d \n" - ".p2align 5 \n" - "lea (%%rax),%%eax \n" - "lea (%%rbx),%%ebx \n" - "lea (%%rcx),%%ecx \n" - "lea (%%rdx),%%edx \n" - "lea (%%rsi),%%esi \n" - "lea (%%rdi),%%edi \n" - "lea (%%rbp),%%ebp \n" - "lea (%%rsp),%%esp \n" - ".p2align 5 \n" - "lea (%%r8),%%r8d \n" - "lea (%%r9),%%r9d \n" - "lea (%%r10),%%r10d \n" - "lea (%%r11),%%r11d \n" - "lea (%%r12),%%r12d \n" - "lea (%%r13),%%r13d \n" - "lea (%%r14),%%r14d \n" - "lea (%%r15),%%r15d \n" - - ".p2align 5 \n" - "lea 0x10(%%rax),%%eax \n" - "lea 0x10(%%rbx),%%ebx \n" - "lea 0x10(%%rcx),%%ecx \n" - "lea 0x10(%%rdx),%%edx \n" - "lea 0x10(%%rsi),%%esi \n" - "lea 0x10(%%rdi),%%edi \n" - "lea 0x10(%%rbp),%%ebp \n" - "lea 0x10(%%rsp),%%esp \n" - ".p2align 5 \n" - "lea 0x10(%%r8),%%r8d \n" - "lea 0x10(%%r9),%%r9d \n" - "lea 0x10(%%r10),%%r10d \n" - "lea 0x10(%%r11),%%r11d \n" - "lea 0x10(%%r12),%%r12d \n" - "lea 0x10(%%r13),%%r13d \n" - "lea 0x10(%%r14),%%r14d \n" - "lea 0x10(%%r15),%%r15d \n" - - ".p2align 5 \n" - "add 0x10,%%eax \n" - "add 0x10,%%ebx \n" - "add 0x10,%%ecx \n" - "add 0x10,%%edx \n" - "add 0x10,%%esi \n" - "add 0x10,%%edi \n" - "add 0x10,%%ebp \n" - "add 0x10,%%esp \n" - ".p2align 5 \n" - "add 0x10,%%r8d \n" - "add 0x10,%%r9d \n" - "add 0x10,%%r10d \n" - "add 0x10,%%r11d \n" - "add 0x10,%%r12d \n" - "add 0x10,%%r13d \n" - "add 0x10,%%r14d \n" - "add 0x10,%%r15d \n" - - ".p2align 2 \n" - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_y), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // TESTING - -#ifdef HAS_I400TOARGBROW_SSE2 -void I400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pslld $0x18,%%xmm5 \n" - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm0,%%xmm0 \n" - "punpckhwd %%xmm1,%%xmm1 \n" - "por %%xmm5,%%xmm0 \n" - "por %%xmm5,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_y), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void I400ToARGBRow_Unaligned_SSE2(const uint8* src_y, uint8* dst_argb, - int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pslld $0x18,%%xmm5 \n" - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm0,%%xmm0 \n" - "punpckhwd %%xmm1,%%xmm1 \n" - "por %%xmm5,%%xmm0 \n" - "por %%xmm5,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "movdqu %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_y), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_I400TOARGBROW_SSE2 - -#ifdef HAS_RGB24TOARGBROW_SSSE3 -void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" // generate mask 0xff000000 - "pslld $0x18,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm3 \n" - "lea " MEMLEA(0x30,0) ",%0 \n" - "movdqa %%xmm3,%%xmm2 \n" - "palignr $0x8,%%xmm1,%%xmm2 \n" - "pshufb %%xmm4,%%xmm2 \n" - "por %%xmm5,%%xmm2 \n" - "palignr $0xc,%%xmm0,%%xmm1 \n" - "pshufb %%xmm4,%%xmm0 \n" - "movdqa %%xmm2," MEMACCESS2(0x20,1) " \n" - "por %%xmm5,%%xmm0 \n" - "pshufb %%xmm4,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "por %%xmm5,%%xmm1 \n" - "palignr $0x4,%%xmm3,%%xmm3 \n" - "pshufb %%xmm4,%%xmm3 \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "por %%xmm5,%%xmm3 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm3," MEMACCESS2(0x30,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_rgb24), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : "m"(kShuffleMaskRGB24ToARGB) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" // generate mask 0xff000000 - "pslld $0x18,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm3 \n" - "lea " MEMLEA(0x30,0) ",%0 \n" - "movdqa %%xmm3,%%xmm2 \n" - "palignr $0x8,%%xmm1,%%xmm2 \n" - "pshufb %%xmm4,%%xmm2 \n" - "por %%xmm5,%%xmm2 \n" - "palignr $0xc,%%xmm0,%%xmm1 \n" - "pshufb %%xmm4,%%xmm0 \n" - "movdqa %%xmm2," MEMACCESS2(0x20,1) " \n" - "por %%xmm5,%%xmm0 \n" - "pshufb %%xmm4,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "por %%xmm5,%%xmm1 \n" - "palignr $0x4,%%xmm3,%%xmm3 \n" - "pshufb %%xmm4,%%xmm3 \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "por %%xmm5,%%xmm3 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm3," MEMACCESS2(0x30,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_raw), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : "m"(kShuffleMaskRAWToARGB) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void RGB565ToARGBRow_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "mov $0x1080108,%%eax \n" - "movd %%eax,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "mov $0x20802080,%%eax \n" - "movd %%eax,%%xmm6 \n" - "pshufd $0x0,%%xmm6,%%xmm6 \n" - "pcmpeqb %%xmm3,%%xmm3 \n" - "psllw $0xb,%%xmm3 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "psllw $0xa,%%xmm4 \n" - "psrlw $0x5,%%xmm4 \n" - "pcmpeqb %%xmm7,%%xmm7 \n" - "psllw $0x8,%%xmm7 \n" - "sub %0,%1 \n" - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "pand %%xmm3,%%xmm1 \n" - "psllw $0xb,%%xmm2 \n" - "pmulhuw %%xmm5,%%xmm1 \n" - "pmulhuw %%xmm5,%%xmm2 \n" - "psllw $0x8,%%xmm1 \n" - "por %%xmm2,%%xmm1 \n" - "pand %%xmm4,%%xmm0 \n" - "pmulhuw %%xmm6,%%xmm0 \n" - "por %%xmm7,%%xmm0 \n" - "movdqa %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm0,%%xmm1 \n" - "punpckhbw %%xmm0,%%xmm2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm1,0x00,1,0,2) // movdqa %%xmm1,(%1,%0,2) - MEMOPMEM(movdqa,xmm2,0x10,1,0,2) // movdqa %%xmm2,0x10(%1,%0,2) - "lea " MEMLEA(0x10,0) ",%0 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc", "eax" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ARGB1555ToARGBRow_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "mov $0x1080108,%%eax \n" - "movd %%eax,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "mov $0x42004200,%%eax \n" - "movd %%eax,%%xmm6 \n" - "pshufd $0x0,%%xmm6,%%xmm6 \n" - "pcmpeqb %%xmm3,%%xmm3 \n" - "psllw $0xb,%%xmm3 \n" - "movdqa %%xmm3,%%xmm4 \n" - "psrlw $0x6,%%xmm4 \n" - "pcmpeqb %%xmm7,%%xmm7 \n" - "psllw $0x8,%%xmm7 \n" - "sub %0,%1 \n" - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psllw $0x1,%%xmm1 \n" - "psllw $0xb,%%xmm2 \n" - "pand %%xmm3,%%xmm1 \n" - "pmulhuw %%xmm5,%%xmm2 \n" - "pmulhuw %%xmm5,%%xmm1 \n" - "psllw $0x8,%%xmm1 \n" - "por %%xmm2,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "pand %%xmm4,%%xmm0 \n" - "psraw $0x8,%%xmm2 \n" - "pmulhuw %%xmm6,%%xmm0 \n" - "pand %%xmm7,%%xmm2 \n" - "por %%xmm2,%%xmm0 \n" - "movdqa %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm0,%%xmm1 \n" - "punpckhbw %%xmm0,%%xmm2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm1,0x00,1,0,2) // movdqa %%xmm1,(%1,%0,2) - MEMOPMEM(movdqa,xmm2,0x10,1,0,2) // movdqa %%xmm2,0x10(%1,%0,2) - "lea " MEMLEA(0x10,0) ",%0 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc", "eax" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ARGB4444ToARGBRow_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "mov $0xf0f0f0f,%%eax \n" - "movd %%eax,%%xmm4 \n" - "pshufd $0x0,%%xmm4,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "pslld $0x4,%%xmm5 \n" - "sub %0,%1 \n" - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "pand %%xmm4,%%xmm0 \n" - "pand %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm3 \n" - "psllw $0x4,%%xmm1 \n" - "psrlw $0x4,%%xmm3 \n" - "por %%xmm1,%%xmm0 \n" - "por %%xmm3,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm0 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,2) // movdqa %%xmm0,(%1,%0,2) - MEMOPMEM(movdqa,xmm1,0x10,1,0,2) // movdqa %%xmm1,0x10(%1,%0,2) - "lea " MEMLEA(0x10,0) ",%0 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc", "eax" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ARGBToRGB24Row_SSSE3(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "movdqa %3,%%xmm6 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "pshufb %%xmm6,%%xmm0 \n" - "pshufb %%xmm6,%%xmm1 \n" - "pshufb %%xmm6,%%xmm2 \n" - "pshufb %%xmm6,%%xmm3 \n" - "movdqa %%xmm1,%%xmm4 \n" - "psrldq $0x4,%%xmm1 \n" - "pslldq $0xc,%%xmm4 \n" - "movdqa %%xmm2,%%xmm5 \n" - "por %%xmm4,%%xmm0 \n" - "pslldq $0x8,%%xmm5 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "por %%xmm5,%%xmm1 \n" - "psrldq $0x8,%%xmm2 \n" - "pslldq $0x4,%%xmm3 \n" - "por %%xmm3,%%xmm2 \n" - "movdqu %%xmm1," MEMACCESS2(0x10,1) " \n" - "movdqu %%xmm2," MEMACCESS2(0x20,1) " \n" - "lea " MEMLEA(0x30,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : "m"(kShuffleMaskARGBToRGB24) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -void ARGBToRAWRow_SSSE3(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "movdqa %3,%%xmm6 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "pshufb %%xmm6,%%xmm0 \n" - "pshufb %%xmm6,%%xmm1 \n" - "pshufb %%xmm6,%%xmm2 \n" - "pshufb %%xmm6,%%xmm3 \n" - "movdqa %%xmm1,%%xmm4 \n" - "psrldq $0x4,%%xmm1 \n" - "pslldq $0xc,%%xmm4 \n" - "movdqa %%xmm2,%%xmm5 \n" - "por %%xmm4,%%xmm0 \n" - "pslldq $0x8,%%xmm5 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "por %%xmm5,%%xmm1 \n" - "psrldq $0x8,%%xmm2 \n" - "pslldq $0x4,%%xmm3 \n" - "por %%xmm3,%%xmm2 \n" - "movdqu %%xmm1," MEMACCESS2(0x10,1) " \n" - "movdqu %%xmm2," MEMACCESS2(0x20,1) " \n" - "lea " MEMLEA(0x30,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : "m"(kShuffleMaskARGBToRAW) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -void ARGBToRGB565Row_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "pcmpeqb %%xmm3,%%xmm3 \n" - "psrld $0x1b,%%xmm3 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "psrld $0x1a,%%xmm4 \n" - "pslld $0x5,%%xmm4 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pslld $0xb,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "pslld $0x8,%%xmm0 \n" - "psrld $0x3,%%xmm1 \n" - "psrld $0x5,%%xmm2 \n" - "psrad $0x10,%%xmm0 \n" - "pand %%xmm3,%%xmm1 \n" - "pand %%xmm4,%%xmm2 \n" - "pand %%xmm5,%%xmm0 \n" - "por %%xmm2,%%xmm1 \n" - "por %%xmm1,%%xmm0 \n" - "packssdw %%xmm0,%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ARGBToARGB1555Row_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "pcmpeqb %%xmm4,%%xmm4 \n" - "psrld $0x1b,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "pslld $0x5,%%xmm5 \n" - "movdqa %%xmm4,%%xmm6 \n" - "pslld $0xa,%%xmm6 \n" - "pcmpeqb %%xmm7,%%xmm7 \n" - "pslld $0xf,%%xmm7 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm0,%%xmm3 \n" - "psrad $0x10,%%xmm0 \n" - "psrld $0x3,%%xmm1 \n" - "psrld $0x6,%%xmm2 \n" - "psrld $0x9,%%xmm3 \n" - "pand %%xmm7,%%xmm0 \n" - "pand %%xmm4,%%xmm1 \n" - "pand %%xmm5,%%xmm2 \n" - "pand %%xmm6,%%xmm3 \n" - "por %%xmm1,%%xmm0 \n" - "por %%xmm3,%%xmm2 \n" - "por %%xmm2,%%xmm0 \n" - "packssdw %%xmm0,%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMACCESS2(0x8,1) ",%1 \n" - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ARGBToARGB4444Row_SSE2(const uint8* src, uint8* dst, int pix) { - asm volatile ( - "pcmpeqb %%xmm4,%%xmm4 \n" - "psllw $0xc,%%xmm4 \n" - "movdqa %%xmm4,%%xmm3 \n" - "psrlw $0x8,%%xmm3 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm3,%%xmm0 \n" - "pand %%xmm4,%%xmm1 \n" - "psrlq $0x4,%%xmm0 \n" - "psrlq $0x8,%%xmm1 \n" - "por %%xmm1,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" -#endif - ); -} -#endif // HAS_RGB24TOARGBROW_SSSE3 - -#ifdef HAS_ARGBTOYROW_SSSE3 -void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kARGBToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kARGBToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBTOYROW_SSSE3 - -#ifdef HAS_ARGBTOYJROW_SSSE3 -void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "paddw %%xmm5,%%xmm0 \n" - "paddw %%xmm5,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kARGBToYJ), // %3 - "m"(kAddYJ64) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "paddw %%xmm5,%%xmm0 \n" - "paddw %%xmm5,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kARGBToYJ), // %3 - "m"(kAddYJ64) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBTOYJROW_SSSE3 - -#ifdef HAS_ARGBTOUVROW_SSSE3 -// TODO(fbarchard): pass xmm constants to single block of assembly. -// fpic on GCC 4.2 for OSX runs out of GPR registers. "m" effectively takes -// 3 registers - ebx, ebp and eax. "m" can be passed with 3 normal registers, -// or 4 if stack frame is disabled. Doing 2 assembly blocks is a work around -// and considered unsafe. -void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(pavgb,0x00,0,4,1,xmm0) // pavgb (%0,%4,1),%%xmm0 - MEMOPREG(pavgb,0x10,0,4,1,xmm1) // pavgb 0x10(%0,%4,1),%%xmm1 - MEMOPREG(pavgb,0x20,0,4,1,xmm2) // pavgb 0x20(%0,%4,1),%%xmm2 - MEMOPREG(pavgb,0x30,0,4,1,xmm6) // pavgb 0x30(%0,%4,1),%%xmm6 - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_argb)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -// TODO(fbarchard): Share code with ARGBToUVRow_SSSE3. -void ARGBToUVJRow_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToUJ), // %0 - "m"(kARGBToVJ), // %1 - "m"(kAddUVJ128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(pavgb,0x00,0,4,1,xmm0) // pavgb (%0,%4,1),%%xmm0 - MEMOPREG(pavgb,0x10,0,4,1,xmm1) // pavgb 0x10(%0,%4,1),%%xmm1 - MEMOPREG(pavgb,0x20,0,4,1,xmm2) // pavgb 0x20(%0,%4,1),%%xmm2 - MEMOPREG(pavgb,0x30,0,4,1,xmm6) // pavgb 0x30(%0,%4,1),%%xmm6 - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "paddw %%xmm5,%%xmm0 \n" - "paddw %%xmm5,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_argb)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ARGBToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm7) // movdqu (%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm0 \n" - MEMOPREG(movdqu,0x10,0,4,1,xmm7) // movdqu 0x10(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm1 \n" - MEMOPREG(movdqu,0x20,0,4,1,xmm7) // movdqu 0x20(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm2 \n" - MEMOPREG(movdqu,0x30,0,4,1,xmm7) // movdqu 0x30(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_argb)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ARGBToUVJRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToUJ), // %0 - "m"(kARGBToVJ), // %1 - "m"(kAddUVJ128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm7) // movdqu (%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm0 \n" - MEMOPREG(movdqu,0x10,0,4,1,xmm7) // movdqu 0x10(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm1 \n" - MEMOPREG(movdqu,0x20,0,4,1,xmm7) // movdqu 0x20(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm2 \n" - MEMOPREG(movdqu,0x30,0,4,1,xmm7) // movdqu 0x30(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "paddw %%xmm5,%%xmm0 \n" - "paddw %%xmm5,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_argb)) - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ARGBToUV444Row_SSSE3(const uint8* src_argb, uint8* dst_u, uint8* dst_v, - int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm6 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm6,%%xmm2 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm2 \n" - "packsswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "pmaddubsw %%xmm3,%%xmm0 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm6,%%xmm2 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm2 \n" - "packsswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,2,1) // movdqa %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6" -#endif - ); -} - -void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_u, - uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm6 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm6,%%xmm2 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm2 \n" - "packsswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "pmaddubsw %%xmm3,%%xmm0 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm6,%%xmm2 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm2 \n" - "packsswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,2,1) // movdqu %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6" -#endif - ); -} - -void ARGBToUV422Row_SSSE3(const uint8* src_argb0, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ARGBToUV422Row_Unaligned_SSSE3(const uint8* src_argb0, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kARGBToU), // %0 - "m"(kARGBToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void BGRAToYRow_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_bgra), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kBGRAToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void BGRAToYRow_Unaligned_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_bgra), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kBGRAToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void BGRAToUVRow_SSSE3(const uint8* src_bgra0, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kBGRAToU), // %0 - "m"(kBGRAToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(pavgb,0x00,0,4,1,xmm0) // pavgb (%0,%4,1),%%xmm0 - MEMOPREG(pavgb,0x10,0,4,1,xmm1) // pavgb 0x10(%0,%4,1),%%xmm1 - MEMOPREG(pavgb,0x20,0,4,1,xmm2) // pavgb 0x20(%0,%4,1),%%xmm2 - MEMOPREG(pavgb,0x30,0,4,1,xmm6) // pavgb 0x30(%0,%4,1),%%xmm6 - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_bgra0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_bgra)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void BGRAToUVRow_Unaligned_SSSE3(const uint8* src_bgra0, int src_stride_bgra, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kBGRAToU), // %0 - "m"(kBGRAToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm7) // movdqu (%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm0 \n" - MEMOPREG(movdqu,0x10,0,4,1,xmm7) // movdqu 0x10(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm1 \n" - MEMOPREG(movdqu,0x20,0,4,1,xmm7) // movdqu 0x20(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm2 \n" - MEMOPREG(movdqu,0x30,0,4,1,xmm7) // movdqu 0x30(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_bgra0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_bgra)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ABGRToYRow_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_abgr), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kABGRToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ABGRToYRow_Unaligned_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_abgr), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kABGRToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void RGBAToYRow_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_rgba), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kRGBAToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void RGBAToYRow_Unaligned_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix) { - asm volatile ( - "movdqa %4,%%xmm5 \n" - "movdqa %3,%%xmm4 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "phaddw %%xmm1,%%xmm0 \n" - "phaddw %%xmm3,%%xmm2 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_rgba), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : "m"(kRGBAToY), // %3 - "m"(kAddY16) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ABGRToUVRow_SSSE3(const uint8* src_abgr0, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kABGRToU), // %0 - "m"(kABGRToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(pavgb,0x00,0,4,1,xmm0) // pavgb (%0,%4,1),%%xmm0 - MEMOPREG(pavgb,0x10,0,4,1,xmm1) // pavgb 0x10(%0,%4,1),%%xmm1 - MEMOPREG(pavgb,0x20,0,4,1,xmm2) // pavgb 0x20(%0,%4,1),%%xmm2 - MEMOPREG(pavgb,0x30,0,4,1,xmm6) // pavgb 0x30(%0,%4,1),%%xmm6 - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_abgr0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_abgr)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void ABGRToUVRow_Unaligned_SSSE3(const uint8* src_abgr0, int src_stride_abgr, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kABGRToU), // %0 - "m"(kABGRToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm7) // movdqu (%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm0 \n" - MEMOPREG(movdqu,0x10,0,4,1,xmm7) // movdqu 0x10(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm1 \n" - MEMOPREG(movdqu,0x20,0,4,1,xmm7) // movdqu 0x20(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm2 \n" - MEMOPREG(movdqu,0x30,0,4,1,xmm7) // movdqu 0x30(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_abgr0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_abgr)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void RGBAToUVRow_SSSE3(const uint8* src_rgba0, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kRGBAToU), // %0 - "m"(kRGBAToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(pavgb,0x00,0,4,1,xmm0) // pavgb (%0,%4,1),%%xmm0 - MEMOPREG(pavgb,0x10,0,4,1,xmm1) // pavgb 0x10(%0,%4,1),%%xmm1 - MEMOPREG(pavgb,0x20,0,4,1,xmm2) // pavgb 0x20(%0,%4,1),%%xmm2 - MEMOPREG(pavgb,0x30,0,4,1,xmm6) // pavgb 0x30(%0,%4,1),%%xmm6 - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_rgba0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_rgba)) - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} - -void RGBAToUVRow_Unaligned_SSSE3(const uint8* src_rgba0, int src_stride_rgba, - uint8* dst_u, uint8* dst_v, int width) { - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kRGBAToU), // %0 - "m"(kRGBAToV), // %1 - "m"(kAddUV128) // %2 - ); - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqu " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqu " MEMACCESS2(0x30,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm7) // movdqu (%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm0 \n" - MEMOPREG(movdqu,0x10,0,4,1,xmm7) // movdqu 0x10(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm1 \n" - MEMOPREG(movdqu,0x20,0,4,1,xmm7) // movdqu 0x20(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm2 \n" - MEMOPREG(movdqu,0x30,0,4,1,xmm7) // movdqu 0x30(%0,%4,1),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movlps %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhps,xmm0,0x00,1,2,1) // movhps %%xmm0,(%1,%2,1) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_rgba0), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t)(src_stride_rgba)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBTOUVROW_SSSE3 - -#ifdef HAS_I422TOARGBROW_SSSE3 -#define UB 127 /* min(63,(int8)(2.018 * 64)) */ -#define UG -25 /* (int8)(-0.391 * 64 - 0.5) */ -#define UR 0 - -#define VB 0 -#define VG -52 /* (int8)(-0.813 * 64 - 0.5) */ -#define VR 102 /* (int8)(1.596 * 64 + 0.5) */ - -// Bias -#define BB UB * 128 + VB * 128 -#define BG UG * 128 + VG * 128 -#define BR UR * 128 + VR * 128 - -#define YG 74 /* (int8)(1.164 * 64 + 0.5) */ - -struct { - vec8 kUVToB; // 0 - vec8 kUVToG; // 16 - vec8 kUVToR; // 32 - vec16 kUVBiasB; // 48 - vec16 kUVBiasG; // 64 - vec16 kUVBiasR; // 80 - vec16 kYSub16; // 96 - vec16 kYToRgb; // 112 - vec8 kVUToB; // 128 - vec8 kVUToG; // 144 - vec8 kVUToR; // 160 -} static SIMD_ALIGNED(kYuvConstants) = { - { UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB }, - { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, - { UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR }, - { BB, BB, BB, BB, BB, BB, BB, BB }, - { BG, BG, BG, BG, BG, BG, BG, BG }, - { BR, BR, BR, BR, BR, BR, BR, BR }, - { 16, 16, 16, 16, 16, 16, 16, 16 }, - { YG, YG, YG, YG, YG, YG, YG, YG }, - { VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB }, - { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, - { VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR } -}; - - -// Read 8 UV from 411 -#define READYUV444 \ - "movq " MEMACCESS([u_buf]) ",%%xmm0 \n" \ - BUNDLEALIGN \ - MEMOPREG(movq, 0x00, [u_buf], [v_buf], 1, xmm1) \ - "lea " MEMLEA(0x8, [u_buf]) ",%[u_buf] \n" \ - "punpcklbw %%xmm1,%%xmm0 \n" - -// Read 4 UV from 422, upsample to 8 UV -#define READYUV422 \ - "movd " MEMACCESS([u_buf]) ",%%xmm0 \n" \ - BUNDLEALIGN \ - MEMOPREG(movd, 0x00, [u_buf], [v_buf], 1, xmm1) \ - "lea " MEMLEA(0x4, [u_buf]) ",%[u_buf] \n" \ - "punpcklbw %%xmm1,%%xmm0 \n" \ - "punpcklwd %%xmm0,%%xmm0 \n" - -// Read 2 UV from 411, upsample to 8 UV -#define READYUV411 \ - "movd " MEMACCESS([u_buf]) ",%%xmm0 \n" \ - BUNDLEALIGN \ - MEMOPREG(movd, 0x00, [u_buf], [v_buf], 1, xmm1) \ - "lea " MEMLEA(0x2, [u_buf]) ",%[u_buf] \n" \ - "punpcklbw %%xmm1,%%xmm0 \n" \ - "punpcklwd %%xmm0,%%xmm0 \n" \ - "punpckldq %%xmm0,%%xmm0 \n" - -// Read 4 UV from NV12, upsample to 8 UV -#define READNV12 \ - "movq " MEMACCESS([uv_buf]) ",%%xmm0 \n" \ - "lea " MEMLEA(0x8, [uv_buf]) ",%[uv_buf] \n" \ - "punpcklwd %%xmm0,%%xmm0 \n" - -// Convert 8 pixels: 8 UV and 8 Y -#define YUVTORGB \ - "movdqa %%xmm0,%%xmm1 \n" \ - "movdqa %%xmm0,%%xmm2 \n" \ - "pmaddubsw " MEMACCESS([kYuvConstants]) ",%%xmm0 \n" \ - "pmaddubsw " MEMACCESS2(16, [kYuvConstants]) ",%%xmm1 \n" \ - "pmaddubsw " MEMACCESS2(32, [kYuvConstants]) ",%%xmm2 \n" \ - "psubw " MEMACCESS2(48, [kYuvConstants]) ",%%xmm0 \n" \ - "psubw " MEMACCESS2(64, [kYuvConstants]) ",%%xmm1 \n" \ - "psubw " MEMACCESS2(80, [kYuvConstants]) ",%%xmm2 \n" \ - "movq " MEMACCESS([y_buf]) ",%%xmm3 \n" \ - "lea " MEMLEA(0x8, [y_buf]) ",%[y_buf] \n" \ - "punpcklbw %%xmm4,%%xmm3 \n" \ - "psubsw " MEMACCESS2(96, [kYuvConstants]) ",%%xmm3 \n" \ - "pmullw " MEMACCESS2(112, [kYuvConstants]) ",%%xmm3 \n" \ - "paddsw %%xmm3,%%xmm0 \n" \ - "paddsw %%xmm3,%%xmm1 \n" \ - "paddsw %%xmm3,%%xmm2 \n" \ - "psraw $0x6,%%xmm0 \n" \ - "psraw $0x6,%%xmm1 \n" \ - "psraw $0x6,%%xmm2 \n" \ - "packuswb %%xmm0,%%xmm0 \n" \ - "packuswb %%xmm1,%%xmm1 \n" \ - "packuswb %%xmm2,%%xmm2 \n" - -// Convert 8 pixels: 8 VU and 8 Y -#define YVUTORGB \ - "movdqa %%xmm0,%%xmm1 \n" \ - "movdqa %%xmm0,%%xmm2 \n" \ - "pmaddubsw " MEMACCESS2(128, [kYuvConstants]) ",%%xmm0 \n" \ - "pmaddubsw " MEMACCESS2(144, [kYuvConstants]) ",%%xmm1 \n" \ - "pmaddubsw " MEMACCESS2(160, [kYuvConstants]) ",%%xmm2 \n" \ - "psubw " MEMACCESS2(48, [kYuvConstants]) ",%%xmm0 \n" \ - "psubw " MEMACCESS2(64, [kYuvConstants]) ",%%xmm1 \n" \ - "psubw " MEMACCESS2(80, [kYuvConstants]) ",%%xmm2 \n" \ - "movq " MEMACCESS([y_buf]) ",%%xmm3 \n" \ - "lea " MEMLEA(0x8, [y_buf]) ",%[y_buf] \n" \ - "punpcklbw %%xmm4,%%xmm3 \n" \ - "psubsw " MEMACCESS2(96, [kYuvConstants]) ",%%xmm3 \n" \ - "pmullw " MEMACCESS2(112, [kYuvConstants]) ",%%xmm3 \n" \ - "paddsw %%xmm3,%%xmm0 \n" \ - "paddsw %%xmm3,%%xmm1 \n" \ - "paddsw %%xmm3,%%xmm2 \n" \ - "psraw $0x6,%%xmm0 \n" \ - "psraw $0x6,%%xmm1 \n" \ - "psraw $0x6,%%xmm2 \n" \ - "packuswb %%xmm0,%%xmm0 \n" \ - "packuswb %%xmm1,%%xmm1 \n" \ - "packuswb %%xmm2,%%xmm2 \n" - -void OMITFP I444ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV444 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS([dst_argb]) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_argb]) " \n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToRGB24Row_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_rgb24, - int width) { -// fpic 32 bit gcc 4.2 on OSX runs out of GPR regs. -#if defined(__i386__) - asm volatile ( - "movdqa %[kShuffleMaskARGBToRGB24_0],%%xmm5 \n" - "movdqa %[kShuffleMaskARGBToRGB24],%%xmm6 \n" - :: [kShuffleMaskARGBToRGB24_0]"m"(kShuffleMaskARGBToRGB24_0), - [kShuffleMaskARGBToRGB24]"m"(kShuffleMaskARGBToRGB24)); -#endif - - asm volatile ( -#if !defined(__i386__) - "movdqa %[kShuffleMaskARGBToRGB24_0],%%xmm5 \n" - "movdqa %[kShuffleMaskARGBToRGB24],%%xmm6 \n" -#endif - "sub %[u_buf],%[v_buf] \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm2,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "pshufb %%xmm5,%%xmm0 \n" - "pshufb %%xmm6,%%xmm1 \n" - "palignr $0xc,%%xmm0,%%xmm1 \n" - "movq %%xmm0," MEMACCESS([dst_rgb24]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x8,[dst_rgb24]) "\n" - "lea " MEMLEA(0x18,[dst_rgb24]) ",%[dst_rgb24] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_rgb24]"+r"(dst_rgb24), // %[dst_rgb24] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) -#if !defined(__i386__) - , [kShuffleMaskARGBToRGB24_0]"m"(kShuffleMaskARGBToRGB24_0), - [kShuffleMaskARGBToRGB24]"m"(kShuffleMaskARGBToRGB24) -#endif - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -void OMITFP I422ToRAWRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_raw, - int width) { -// fpic 32 bit gcc 4.2 on OSX runs out of GPR regs. -#if defined(__i386__) - asm volatile ( - "movdqa %[kShuffleMaskARGBToRAW_0],%%xmm5 \n" - "movdqa %[kShuffleMaskARGBToRAW],%%xmm6 \n" - :: [kShuffleMaskARGBToRAW_0]"m"(kShuffleMaskARGBToRAW_0), - [kShuffleMaskARGBToRAW]"m"(kShuffleMaskARGBToRAW)); -#endif - - asm volatile ( -#if !defined(__i386__) - "movdqa %[kShuffleMaskARGBToRAW_0],%%xmm5 \n" - "movdqa %[kShuffleMaskARGBToRAW],%%xmm6 \n" -#endif - "sub %[u_buf],%[v_buf] \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm2,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "pshufb %%xmm5,%%xmm0 \n" - "pshufb %%xmm6,%%xmm1 \n" - "palignr $0xc,%%xmm0,%%xmm1 \n" - "movq %%xmm0," MEMACCESS([dst_raw]) " \n" - "movdqu %%xmm1," MEMACCESS2(0x8,[dst_raw]) "\n" - "lea " MEMLEA(0x18,[dst_raw]) ",%[dst_raw] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_raw]"+r"(dst_raw), // %[dst_raw] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) -#if !defined(__i386__) - , [kShuffleMaskARGBToRAW_0]"m"(kShuffleMaskARGBToRAW_0), - [kShuffleMaskARGBToRAW]"m"(kShuffleMaskARGBToRAW) -#endif - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -void OMITFP I422ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I411ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV411 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP NV12ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READNV12 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [uv_buf]"+r"(uv_buf), // %[uv_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" - // Does not use r14. -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP NV21ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READNV12 - YVUTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [uv_buf]"+r"(uv_buf), // %[uv_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" - // Does not use r14. -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I444ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV444 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I411ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV411 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP NV12ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READNV12 - YUVTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [uv_buf]"+r"(uv_buf), // %[uv_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" - // Does not use r14. -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP NV21ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READNV12 - YVUTORGB - "punpcklbw %%xmm1,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpckhwd %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS([dst_argb]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_argb]) "\n" - "lea " MEMLEA(0x20,[dst_argb]) ",%[dst_argb] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [uv_buf]"+r"(uv_buf), // %[uv_buf] - [dst_argb]"+r"(dst_argb), // %[dst_argb] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" - // Does not use r14. -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToBGRARow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_bgra, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "pcmpeqb %%xmm5,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm5 \n" - "movdqa %%xmm5,%%xmm0 \n" - "punpcklwd %%xmm1,%%xmm5 \n" - "punpckhwd %%xmm1,%%xmm0 \n" - "movdqa %%xmm5," MEMACCESS([dst_bgra]) "\n" - "movdqa %%xmm0," MEMACCESS2(0x10,[dst_bgra]) "\n" - "lea " MEMLEA(0x20,[dst_bgra]) ",%[dst_bgra] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_bgra]"+r"(dst_bgra), // %[dst_bgra] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToABGRRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_abgr, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "punpcklwd %%xmm0,%%xmm2 \n" - "punpckhwd %%xmm0,%%xmm1 \n" - "movdqa %%xmm2," MEMACCESS([dst_abgr]) "\n" - "movdqa %%xmm1," MEMACCESS2(0x10,[dst_abgr]) "\n" - "lea " MEMLEA(0x20,[dst_abgr]) ",%[dst_abgr] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_abgr]"+r"(dst_abgr), // %[dst_abgr] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToRGBARow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_rgba, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "pcmpeqb %%xmm5,%%xmm5 \n" - "punpcklbw %%xmm2,%%xmm1 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "movdqa %%xmm5,%%xmm0 \n" - "punpcklwd %%xmm1,%%xmm5 \n" - "punpckhwd %%xmm1,%%xmm0 \n" - "movdqa %%xmm5," MEMACCESS([dst_rgba]) "\n" - "movdqa %%xmm0," MEMACCESS2(0x10,[dst_rgba]) "\n" - "lea " MEMLEA(0x20,[dst_rgba]) ",%[dst_rgba] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_rgba]"+r"(dst_rgba), // %[dst_rgba] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToBGRARow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_bgra, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "pcmpeqb %%xmm5,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm5 \n" - "movdqa %%xmm5,%%xmm0 \n" - "punpcklwd %%xmm1,%%xmm5 \n" - "punpckhwd %%xmm1,%%xmm0 \n" - "movdqu %%xmm5," MEMACCESS([dst_bgra]) "\n" - "movdqu %%xmm0," MEMACCESS2(0x10,[dst_bgra]) "\n" - "lea " MEMLEA(0x20,[dst_bgra]) ",%[dst_bgra] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_bgra]"+r"(dst_bgra), // %[dst_bgra] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToABGRRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_abgr, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "punpcklbw %%xmm1,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "punpcklwd %%xmm0,%%xmm2 \n" - "punpckhwd %%xmm0,%%xmm1 \n" - "movdqu %%xmm2," MEMACCESS([dst_abgr]) "\n" - "movdqu %%xmm1," MEMACCESS2(0x10,[dst_abgr]) "\n" - "lea " MEMLEA(0x20,[dst_abgr]) ",%[dst_abgr] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_abgr]"+r"(dst_abgr), // %[dst_abgr] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void OMITFP I422ToRGBARow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_rgba, - int width) { - asm volatile ( - "sub %[u_buf],%[v_buf] \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - LABELALIGN - "1: \n" - READYUV422 - YUVTORGB - "pcmpeqb %%xmm5,%%xmm5 \n" - "punpcklbw %%xmm2,%%xmm1 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "movdqa %%xmm5,%%xmm0 \n" - "punpcklwd %%xmm1,%%xmm5 \n" - "punpckhwd %%xmm1,%%xmm0 \n" - "movdqu %%xmm5," MEMACCESS([dst_rgba]) "\n" - "movdqu %%xmm0," MEMACCESS2(0x10,[dst_rgba]) "\n" - "lea " MEMLEA(0x20,[dst_rgba]) ",%[dst_rgba] \n" - "sub $0x8,%[width] \n" - "jg 1b \n" - : [y_buf]"+r"(y_buf), // %[y_buf] - [u_buf]"+r"(u_buf), // %[u_buf] - [v_buf]"+r"(v_buf), // %[v_buf] - [dst_rgba]"+r"(dst_rgba), // %[dst_rgba] - [width]"+rm"(width) // %[width] - : [kYuvConstants]"r"(&kYuvConstants.kUVToB) // %[kYuvConstants] - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -#endif // HAS_I422TOARGBROW_SSSE3 - -#ifdef HAS_YTOARGBROW_SSE2 -void YToARGBRow_SSE2(const uint8* y_buf, - uint8* dst_argb, - int width) { - asm volatile ( - "pxor %%xmm5,%%xmm5 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "pslld $0x18,%%xmm4 \n" - "mov $0x00100010,%%eax \n" - "movd %%eax,%%xmm3 \n" - "pshufd $0x0,%%xmm3,%%xmm3 \n" - "mov $0x004a004a,%%eax \n" - "movd %%eax,%%xmm2 \n" - "pshufd $0x0,%%xmm2,%%xmm2 \n" - LABELALIGN - "1: \n" - // Step 1: Scale Y contribution to 8 G values. G = (y - 16) * 1.164 - "movq " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "psubusw %%xmm3,%%xmm0 \n" - "pmullw %%xmm2,%%xmm0 \n" - "psrlw $6, %%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - - // Step 2: Weave into ARGB - "punpcklbw %%xmm0,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm0,%%xmm0 \n" - "punpckhwd %%xmm1,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "por %%xmm4,%%xmm1 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(y_buf), // %0 - "+r"(dst_argb), // %1 - "+rm"(width) // %2 - : - : "memory", "cc", "eax" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" -#endif - ); -} -#endif // HAS_YTOARGBROW_SSE2 - -#ifdef HAS_MIRRORROW_SSSE3 -// Shuffle table for reversing the bytes. -static uvec8 kShuffleMirror = { - 15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u -}; - -void MirrorRow_SSSE3(const uint8* src, uint8* dst, int width) { - intptr_t temp_width = (intptr_t)(width); - asm volatile ( - "movdqa %3,%%xmm5 \n" - "lea " MEMLEA(-0x10,0) ",%0 \n" - LABELALIGN - "1: \n" - MEMOPREG(movdqa,0x00,0,2,1,xmm0) // movdqa (%0,%2),%%xmm0 - "pshufb %%xmm5,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : "m"(kShuffleMirror) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm5" -#endif - ); -} -#endif // HAS_MIRRORROW_SSSE3 - -#ifdef HAS_MIRRORROW_SSE2 -void MirrorRow_SSE2(const uint8* src, uint8* dst, int width) { - intptr_t temp_width = (intptr_t)(width); - asm volatile ( - "lea " MEMLEA(-0x10,0) ",%0 \n" - LABELALIGN - "1: \n" - MEMOPREG(movdqu,0x00,0,2,1,xmm0) // movdqu (%0,%2),%%xmm0 - "movdqa %%xmm0,%%xmm1 \n" - "psllw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm1,%%xmm0 \n" - "pshuflw $0x1b,%%xmm0,%%xmm0 \n" - "pshufhw $0x1b,%%xmm0,%%xmm0 \n" - "pshufd $0x4e,%%xmm0,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1)",%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_MIRRORROW_SSE2 - -#ifdef HAS_MIRRORROW_UV_SSSE3 -// Shuffle table for reversing the bytes of UV channels. -static uvec8 kShuffleMirrorUV = { - 14u, 12u, 10u, 8u, 6u, 4u, 2u, 0u, 15u, 13u, 11u, 9u, 7u, 5u, 3u, 1u -}; -void MirrorUVRow_SSSE3(const uint8* src, uint8* dst_u, uint8* dst_v, - int width) { - intptr_t temp_width = (intptr_t)(width); - asm volatile ( - "movdqa %4,%%xmm1 \n" - "lea " MEMLEA4(-0x10,0,3,2) ",%0 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(-0x10,0) ",%0 \n" - "pshufb %%xmm1,%%xmm0 \n" - "sub $8,%3 \n" - "movlpd %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movhpd,xmm0,0x00,1,2,1) // movhpd %%xmm0,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(temp_width) // %3 - : "m"(kShuffleMirrorUV) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_MIRRORROW_UV_SSSE3 - -#ifdef HAS_ARGBMIRRORROW_SSSE3 -// Shuffle table for reversing the bytes. -static uvec8 kARGBShuffleMirror = { - 12u, 13u, 14u, 15u, 8u, 9u, 10u, 11u, 4u, 5u, 6u, 7u, 0u, 1u, 2u, 3u -}; - -void ARGBMirrorRow_SSSE3(const uint8* src, uint8* dst, int width) { - intptr_t temp_width = (intptr_t)(width); - asm volatile ( - "lea " MEMLEA4(-0x10,0,2,4) ",%0 \n" - "movdqa %3,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "lea " MEMLEA(-0x10,0) ",%0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : "m"(kARGBShuffleMirror) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm5" -#endif - ); -} -#endif // HAS_ARGBMIRRORROW_SSSE3 - -#ifdef HAS_SPLITUVROW_SSE2 -void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "psrlw $0x8,%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "packuswb %%xmm3,%%xmm2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - MEMOPMEM(movdqa,xmm2,0x00,1,2,1) // movdqa %%xmm2,(%1,%2) - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uv), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void SplitUVRow_Unaligned_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "psrlw $0x8,%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "packuswb %%xmm3,%%xmm2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - MEMOPMEM(movdqu,xmm2,0x00,1,2,1) // movdqu %%xmm2,(%1,%2) - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uv), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} -#endif // HAS_SPLITUVROW_SSE2 - -#ifdef HAS_MERGEUVROW_SSE2 -void MergeUVRow_SSE2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, - int width) { - asm volatile ( - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,0,1,1,xmm1) // movdqa (%0,%1,1),%%xmm1 - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm2 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "movdqa %%xmm2," MEMACCESS2(0x10,2) " \n" - "lea " MEMLEA(0x20,2) ",%2 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_u), // %0 - "+r"(src_v), // %1 - "+r"(dst_uv), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2" -#endif - ); -} - -void MergeUVRow_Unaligned_SSE2(const uint8* src_u, const uint8* src_v, - uint8* dst_uv, int width) { - asm volatile ( - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,0,1,1,xmm1) // movdqu (%0,%1,1),%%xmm1 - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm2 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "movdqu %%xmm2," MEMACCESS2(0x10,2) " \n" - "lea " MEMLEA(0x20,2) ",%2 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_u), // %0 - "+r"(src_v), // %1 - "+r"(dst_uv), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2" -#endif - ); -} -#endif // HAS_MERGEUVROW_SSE2 - -#ifdef HAS_COPYROW_SSE2 -void CopyRow_SSE2(const uint8* src, uint8* dst, int count) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(count) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_COPYROW_SSE2 - -#ifdef HAS_COPYROW_X86 -void CopyRow_X86(const uint8* src, uint8* dst, int width) { - size_t width_tmp = (size_t)(width); - asm volatile ( - "shr $0x2,%2 \n" - "rep movsl " MEMMOVESTRING(0,1) " \n" - : "+S"(src), // %0 - "+D"(dst), // %1 - "+c"(width_tmp) // %2 - : - : "memory", "cc" - ); -} -#endif // HAS_COPYROW_X86 - -#ifdef HAS_COPYROW_ERMS -// Unaligned Multiple of 1. -void CopyRow_ERMS(const uint8* src, uint8* dst, int width) { - size_t width_tmp = (size_t)(width); - asm volatile ( - "rep movsb " MEMMOVESTRING(0,1) " \n" - : "+S"(src), // %0 - "+D"(dst), // %1 - "+c"(width_tmp) // %2 - : - : "memory", "cc" - ); -} -#endif // HAS_COPYROW_ERMS - -#ifdef HAS_ARGBCOPYALPHAROW_SSE2 -// width in pixels -void ARGBCopyAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { - asm volatile ( - "pcmpeqb %%xmm0,%%xmm0 \n" - "pslld $0x18,%%xmm0 \n" - "pcmpeqb %%xmm1,%%xmm1 \n" - "psrld $0x8,%%xmm1 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm3 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa " MEMACCESS(1) ",%%xmm4 \n" - "movdqa " MEMACCESS2(0x10,1) ",%%xmm5 \n" - "pand %%xmm0,%%xmm2 \n" - "pand %%xmm0,%%xmm3 \n" - "pand %%xmm1,%%xmm4 \n" - "pand %%xmm1,%%xmm5 \n" - "por %%xmm4,%%xmm2 \n" - "por %%xmm5,%%xmm3 \n" - "movdqa %%xmm2," MEMACCESS(1) " \n" - "movdqa %%xmm3," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBCOPYALPHAROW_SSE2 - -#ifdef HAS_ARGBCOPYALPHAROW_AVX2 -// width in pixels -void ARGBCopyAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { - asm volatile ( - "vpcmpeqb %%ymm0,%%ymm0,%%ymm0 \n" - "vpsrld $0x8,%%ymm0,%%ymm0 \n" - LABELALIGN - "1: \n" - "vmovdqu " MEMACCESS(0) ",%%ymm1 \n" - "vmovdqu " MEMACCESS2(0x20,0) ",%%ymm2 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "vpblendvb %%ymm0," MEMACCESS(1) ",%%ymm1,%%ymm1 \n" - "vpblendvb %%ymm0," MEMACCESS2(0x20,1) ",%%ymm2,%%ymm2 \n" - "vmovdqu %%ymm1," MEMACCESS(1) " \n" - "vmovdqu %%ymm2," MEMACCESS2(0x20,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2" -#endif - ); -} -#endif // HAS_ARGBCOPYALPHAROW_AVX2 - -#ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2 -// width in pixels -void ARGBCopyYToAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { - asm volatile ( - "pcmpeqb %%xmm0,%%xmm0 \n" - "pslld $0x18,%%xmm0 \n" - "pcmpeqb %%xmm1,%%xmm1 \n" - "psrld $0x8,%%xmm1 \n" - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm2 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "punpcklbw %%xmm2,%%xmm2 \n" - "punpckhwd %%xmm2,%%xmm3 \n" - "punpcklwd %%xmm2,%%xmm2 \n" - "movdqa " MEMACCESS(1) ",%%xmm4 \n" - "movdqa " MEMACCESS2(0x10,1) ",%%xmm5 \n" - "pand %%xmm0,%%xmm2 \n" - "pand %%xmm0,%%xmm3 \n" - "pand %%xmm1,%%xmm4 \n" - "pand %%xmm1,%%xmm5 \n" - "por %%xmm4,%%xmm2 \n" - "por %%xmm5,%%xmm3 \n" - "movdqa %%xmm2," MEMACCESS(1) " \n" - "movdqa %%xmm3," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBCOPYYTOALPHAROW_SSE2 - -#ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2 -// width in pixels -void ARGBCopyYToAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { - asm volatile ( - "vpcmpeqb %%ymm0,%%ymm0,%%ymm0 \n" - "vpsrld $0x8,%%ymm0,%%ymm0 \n" - LABELALIGN - "1: \n" - "vpmovzxbd " MEMACCESS(0) ",%%ymm1 \n" - "vpmovzxbd " MEMACCESS2(0x8,0) ",%%ymm2 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "vpslld $0x18,%%ymm1,%%ymm1 \n" - "vpslld $0x18,%%ymm2,%%ymm2 \n" - "vpblendvb %%ymm0," MEMACCESS(1) ",%%ymm1,%%ymm1 \n" - "vpblendvb %%ymm0," MEMACCESS2(0x20,1) ",%%ymm2,%%ymm2 \n" - "vmovdqu %%ymm1," MEMACCESS(1) " \n" - "vmovdqu %%ymm2," MEMACCESS2(0x20,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2" -#endif - ); -} -#endif // HAS_ARGBCOPYYTOALPHAROW_AVX2 - -#ifdef HAS_SETROW_X86 -void SetRow_X86(uint8* dst, uint32 v32, int width) { - size_t width_tmp = (size_t)(width); - asm volatile ( - "shr $0x2,%1 \n" - "rep stosl " MEMSTORESTRING(eax,0) " \n" - : "+D"(dst), // %0 - "+c"(width_tmp) // %1 - : "a"(v32) // %2 - : "memory", "cc"); -} - -void ARGBSetRows_X86(uint8* dst, uint32 v32, int width, - int dst_stride, int height) { - for (int y = 0; y < height; ++y) { - size_t width_tmp = (size_t)(width); - uint32* d = (uint32*)(dst); - asm volatile ( - "rep stosl " MEMSTORESTRING(eax,0) " \n" - : "+D"(d), // %0 - "+c"(width_tmp) // %1 - : "a"(v32) // %2 - : "memory", "cc"); - dst += dst_stride; - } -} -#endif // HAS_SETROW_X86 - -#ifdef HAS_YUY2TOYROW_SSE2 -void YUY2ToYRow_SSE2(const uint8* src_yuy2, uint8* dst_y, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void YUY2ToUVRow_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movdqa,0x00,0,4,1,xmm2) // movdqa (%0,%4,1),%%xmm2 - MEMOPREG(movdqa,0x10,0,4,1,xmm3) // movdqa 0x10(%0,%4,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : "r"((intptr_t)(stride_yuy2)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void YUY2ToUV422Row_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void YUY2ToYRow_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_y, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void YUY2ToUVRow_Unaligned_SSE2(const uint8* src_yuy2, - int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm2) // movdqu (%0,%4,1),%%xmm2 - MEMOPREG(movdqu,0x10,0,4,1,xmm3) // movdqu 0x10(%0,%4,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : "r"((intptr_t)(stride_yuy2)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void YUY2ToUV422Row_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_yuy2), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void UYVYToYRow_SSE2(const uint8* src_uyvy, uint8* dst_y, int pix) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void UYVYToUVRow_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movdqa,0x00,0,4,1,xmm2) // movdqa (%0,%4,1),%%xmm2 - MEMOPREG(movdqa,0x10,0,4,1,xmm3) // movdqa 0x10(%0,%4,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : "r"((intptr_t)(stride_uyvy)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void UYVYToUV422Row_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void UYVYToYRow_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_y, int pix) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_y), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void UYVYToUVRow_Unaligned_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movdqu,0x00,0,4,1,xmm2) // movdqu (%0,%4,1),%%xmm2 - MEMOPREG(movdqu,0x10,0,4,1,xmm3) // movdqu 0x10(%0,%4,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : "r"((intptr_t)(stride_uyvy)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void UYVYToUV422Row_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm1,0x00,1,2,1) // movq %%xmm1,(%1,%2) - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_uyvy), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(pix) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_YUY2TOYROW_SSE2 - -#ifdef HAS_ARGBBLENDROW_SSE2 -// Blend 8 pixels at a time. -void ARGBBlendRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { - asm volatile ( - "pcmpeqb %%xmm7,%%xmm7 \n" - "psrlw $0xf,%%xmm7 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrlw $0x8,%%xmm6 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "psllw $0x8,%%xmm5 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "pslld $0x18,%%xmm4 \n" - "sub $0x1,%3 \n" - "je 91f \n" - "jl 99f \n" - - // 1 pixel loop until destination pointer is aligned. - "10: \n" - "test $0xf,%2 \n" - "je 19f \n" - "movd " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movd " MEMACCESS(1) ",%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "pshufhw $0xf5,%%xmm3,%%xmm3 \n" - "pshuflw $0xf5,%%xmm3,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movd " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x4,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x1,%3 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x4,2) ",%2 \n" - "jge 10b \n" - - "19: \n" - "add $1-4,%3 \n" - "jl 49f \n" - - // 4 pixel loop. - LABELALIGN - "41: \n" - "movdqu " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movdqu " MEMACCESS(1) ",%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "pshufhw $0xf5,%%xmm3,%%xmm3 \n" - "pshuflw $0xf5,%%xmm3,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jge 41b \n" - - "49: \n" - "add $0x3,%3 \n" - "jl 99f \n" - - // 1 pixel loop. - "91: \n" - "movd " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movd " MEMACCESS(1) ",%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "pshufhw $0xf5,%%xmm3,%%xmm3 \n" - "pshuflw $0xf5,%%xmm3,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movd " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x4,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x1,%3 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x4,2) ",%2 \n" - "jge 91b \n" - "99: \n" - : "+r"(src_argb0), // %0 - "+r"(src_argb1), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBBLENDROW_SSE2 - -#ifdef HAS_ARGBBLENDROW_SSSE3 -// Shuffle table for isolating alpha. -static uvec8 kShuffleAlpha = { - 3u, 0x80, 3u, 0x80, 7u, 0x80, 7u, 0x80, - 11u, 0x80, 11u, 0x80, 15u, 0x80, 15u, 0x80 -}; - -// Blend 8 pixels at a time -// Shuffle table for reversing the bytes. - -// Same as SSE2, but replaces -// psrlw xmm3, 8 // alpha -// pshufhw xmm3, xmm3,0F5h // 8 alpha words -// pshuflw xmm3, xmm3,0F5h -// with.. -// pshufb xmm3, kShuffleAlpha // alpha - -void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { - asm volatile ( - "pcmpeqb %%xmm7,%%xmm7 \n" - "psrlw $0xf,%%xmm7 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrlw $0x8,%%xmm6 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "psllw $0x8,%%xmm5 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "pslld $0x18,%%xmm4 \n" - "sub $0x1,%3 \n" - "je 91f \n" - "jl 99f \n" - - // 1 pixel loop until destination pointer is aligned. - "10: \n" - "test $0xf,%2 \n" - "je 19f \n" - "movd " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movd " MEMACCESS(1) ",%%xmm2 \n" - "pshufb %4,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movd " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x4,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x1,%3 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x4,2) ",%2 \n" - "jge 10b \n" - - "19: \n" - "add $1-4,%3 \n" - "jl 49f \n" - "test $0xf,%0 \n" - "jne 41f \n" - "test $0xf,%1 \n" - "jne 41f \n" - - // 4 pixel loop. - LABELALIGN - "40: \n" - "movdqa " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movdqa " MEMACCESS(1) ",%%xmm2 \n" - "pshufb %4,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movdqa " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jge 40b \n" - "jmp 49f \n" - - // 4 pixel unaligned loop. - LABELALIGN - "41: \n" - "movdqu " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movdqu " MEMACCESS(1) ",%%xmm2 \n" - "pshufb %4,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jge 41b \n" - - "49: \n" - "add $0x3,%3 \n" - "jl 99f \n" - - // 1 pixel loop. - "91: \n" - "movd " MEMACCESS(0) ",%%xmm3 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "movdqa %%xmm3,%%xmm0 \n" - "pxor %%xmm4,%%xmm3 \n" - "movd " MEMACCESS(1) ",%%xmm2 \n" - "pshufb %4,%%xmm3 \n" - "pand %%xmm6,%%xmm2 \n" - "paddw %%xmm7,%%xmm3 \n" - "pmullw %%xmm3,%%xmm2 \n" - "movd " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x4,1) ",%1 \n" - "psrlw $0x8,%%xmm1 \n" - "por %%xmm4,%%xmm0 \n" - "pmullw %%xmm3,%%xmm1 \n" - "psrlw $0x8,%%xmm2 \n" - "paddusb %%xmm2,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x1,%3 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x4,2) ",%2 \n" - "jge 91b \n" - "99: \n" - : "+r"(src_argb0), // %0 - "+r"(src_argb1), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : "m"(kShuffleAlpha) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBBLENDROW_SSSE3 - -#ifdef HAS_ARGBATTENUATEROW_SSE2 -// Attenuate 4 pixels at a time. -// aligned to 16 bytes -void ARGBAttenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width) { - asm volatile ( - "pcmpeqb %%xmm4,%%xmm4 \n" - "pslld $0x18,%%xmm4 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrld $0x8,%%xmm5 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "pshufhw $0xff,%%xmm0,%%xmm2 \n" - "pshuflw $0xff,%%xmm2,%%xmm2 \n" - "pmulhuw %%xmm2,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm1 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - "pshufhw $0xff,%%xmm1,%%xmm2 \n" - "pshuflw $0xff,%%xmm2,%%xmm2 \n" - "pmulhuw %%xmm2,%%xmm1 \n" - "movdqa " MEMACCESS(0) ",%%xmm2 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "pand %%xmm4,%%xmm2 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "pand %%xmm5,%%xmm0 \n" - "por %%xmm2,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBATTENUATEROW_SSE2 - -#ifdef HAS_ARGBATTENUATEROW_SSSE3 -// Shuffle table duplicating alpha -static uvec8 kShuffleAlpha0 = { - 3u, 3u, 3u, 3u, 3u, 3u, 128u, 128u, 7u, 7u, 7u, 7u, 7u, 7u, 128u, 128u, -}; -static uvec8 kShuffleAlpha1 = { - 11u, 11u, 11u, 11u, 11u, 11u, 128u, 128u, - 15u, 15u, 15u, 15u, 15u, 15u, 128u, 128u, -}; -// Attenuate 4 pixels at a time. -// aligned to 16 bytes -void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { - asm volatile ( - "pcmpeqb %%xmm3,%%xmm3 \n" - "pslld $0x18,%%xmm3 \n" - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "pshufb %%xmm4,%%xmm0 \n" - "movdqu " MEMACCESS(0) ",%%xmm1 \n" - "punpcklbw %%xmm1,%%xmm1 \n" - "pmulhuw %%xmm1,%%xmm0 \n" - "movdqu " MEMACCESS(0) ",%%xmm1 \n" - "pshufb %%xmm5,%%xmm1 \n" - "movdqu " MEMACCESS(0) ",%%xmm2 \n" - "punpckhbw %%xmm2,%%xmm2 \n" - "pmulhuw %%xmm2,%%xmm1 \n" - "movdqu " MEMACCESS(0) ",%%xmm2 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "pand %%xmm3,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "por %%xmm2,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "m"(kShuffleAlpha0), // %3 - "m"(kShuffleAlpha1) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBATTENUATEROW_SSSE3 - -#ifdef HAS_ARGBUNATTENUATEROW_SSE2 -// Unattenuate 4 pixels at a time. -// aligned to 16 bytes -void ARGBUnattenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, - int width) { - uintptr_t alpha = 0; - asm volatile ( - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movzb " MEMACCESS2(0x03,0) ",%3 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - MEMOPREG(movd,0x00,4,3,4,xmm2) // movd 0x0(%4,%3,4),%%xmm2 - "movzb " MEMACCESS2(0x07,0) ",%3 \n" - MEMOPREG(movd,0x00,4,3,4,xmm3) // movd 0x0(%4,%3,4),%%xmm3 - "pshuflw $0x40,%%xmm2,%%xmm2 \n" - "pshuflw $0x40,%%xmm3,%%xmm3 \n" - "movlhps %%xmm3,%%xmm2 \n" - "pmulhuw %%xmm2,%%xmm0 \n" - "movdqu " MEMACCESS(0) ",%%xmm1 \n" - "movzb " MEMACCESS2(0x0b,0) ",%3 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,4,3,4,xmm2) // movd 0x0(%4,%3,4),%%xmm2 - "movzb " MEMACCESS2(0x0f,0) ",%3 \n" - MEMOPREG(movd,0x00,4,3,4,xmm3) // movd 0x0(%4,%3,4),%%xmm3 - "pshuflw $0x40,%%xmm2,%%xmm2 \n" - "pshuflw $0x40,%%xmm3,%%xmm3 \n" - "movlhps %%xmm3,%%xmm2 \n" - "pmulhuw %%xmm2,%%xmm1 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width), // %2 - "+r"(alpha) // %3 - : "r"(fixed_invtbl8) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBUNATTENUATEROW_SSE2 - -#ifdef HAS_ARGBGRAYROW_SSSE3 -// Convert 8 ARGB pixels (64 bytes) to 8 Gray ARGB pixels -void ARGBGrayRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { - asm volatile ( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "phaddw %%xmm1,%%xmm0 \n" - "paddw %%xmm5,%%xmm0 \n" - "psrlw $0x7,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm3 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrld $0x18,%%xmm2 \n" - "psrld $0x18,%%xmm3 \n" - "packuswb %%xmm3,%%xmm2 \n" - "packuswb %%xmm2,%%xmm2 \n" - "movdqa %%xmm0,%%xmm3 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "punpcklbw %%xmm2,%%xmm3 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm3,%%xmm0 \n" - "punpckhwd %%xmm3,%%xmm1 \n" - "sub $0x8,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "m"(kARGBToYJ), // %3 - "m"(kAddYJ64) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBGRAYROW_SSSE3 - -#ifdef HAS_ARGBSEPIAROW_SSSE3 -// b = (r * 35 + g * 68 + b * 17) >> 7 -// g = (r * 45 + g * 88 + b * 22) >> 7 -// r = (r * 50 + g * 98 + b * 24) >> 7 -// Constant for ARGB color to sepia tone -static vec8 kARGBToSepiaB = { - 17, 68, 35, 0, 17, 68, 35, 0, 17, 68, 35, 0, 17, 68, 35, 0 -}; - -static vec8 kARGBToSepiaG = { - 22, 88, 45, 0, 22, 88, 45, 0, 22, 88, 45, 0, 22, 88, 45, 0 -}; - -static vec8 kARGBToSepiaR = { - 24, 98, 50, 0, 24, 98, 50, 0, 24, 98, 50, 0, 24, 98, 50, 0 -}; - -// Convert 8 ARGB pixels (32 bytes) to 8 Sepia ARGB pixels. -void ARGBSepiaRow_SSSE3(uint8* dst_argb, int width) { - asm volatile ( - "movdqa %2,%%xmm2 \n" - "movdqa %3,%%xmm3 \n" - "movdqa %4,%%xmm4 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm6 \n" - "pmaddubsw %%xmm2,%%xmm0 \n" - "pmaddubsw %%xmm2,%%xmm6 \n" - "phaddw %%xmm6,%%xmm0 \n" - "psrlw $0x7,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm5 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm5 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "phaddw %%xmm1,%%xmm5 \n" - "psrlw $0x7,%%xmm5 \n" - "packuswb %%xmm5,%%xmm5 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm5 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm5 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "phaddw %%xmm1,%%xmm5 \n" - "psrlw $0x7,%%xmm5 \n" - "packuswb %%xmm5,%%xmm5 \n" - "movdqa " MEMACCESS(0) ",%%xmm6 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "psrld $0x18,%%xmm6 \n" - "psrld $0x18,%%xmm1 \n" - "packuswb %%xmm1,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "punpcklbw %%xmm6,%%xmm5 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklwd %%xmm5,%%xmm0 \n" - "punpckhwd %%xmm5,%%xmm1 \n" - "sub $0x8,%1 \n" - "movdqa %%xmm0," MEMACCESS(0) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,0) " \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "jg 1b \n" - : "+r"(dst_argb), // %0 - "+r"(width) // %1 - : "m"(kARGBToSepiaB), // %2 - "m"(kARGBToSepiaG), // %3 - "m"(kARGBToSepiaR) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} -#endif // HAS_ARGBSEPIAROW_SSSE3 - -#ifdef HAS_ARGBCOLORMATRIXROW_SSSE3 -// Tranform 8 ARGB pixels (32 bytes) with color matrix. -// Same as Sepia except matrix is provided. -void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, - const int8* matrix_argb, int width) { - asm volatile ( - "movdqu " MEMACCESS(3) ",%%xmm5 \n" - "pshufd $0x00,%%xmm5,%%xmm2 \n" - "pshufd $0x55,%%xmm5,%%xmm3 \n" - "pshufd $0xaa,%%xmm5,%%xmm4 \n" - "pshufd $0xff,%%xmm5,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm7 \n" - "pmaddubsw %%xmm2,%%xmm0 \n" - "pmaddubsw %%xmm2,%%xmm7 \n" - "movdqa " MEMACCESS(0) ",%%xmm6 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "phaddsw %%xmm7,%%xmm0 \n" - "phaddsw %%xmm1,%%xmm6 \n" - "psraw $0x6,%%xmm0 \n" - "psraw $0x6,%%xmm6 \n" - "packuswb %%xmm0,%%xmm0 \n" - "packuswb %%xmm6,%%xmm6 \n" - "punpcklbw %%xmm6,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm7 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm7 \n" - "phaddsw %%xmm7,%%xmm1 \n" - "movdqa " MEMACCESS(0) ",%%xmm6 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm7 \n" - "pmaddubsw %%xmm5,%%xmm6 \n" - "pmaddubsw %%xmm5,%%xmm7 \n" - "phaddsw %%xmm7,%%xmm6 \n" - "psraw $0x6,%%xmm1 \n" - "psraw $0x6,%%xmm6 \n" - "packuswb %%xmm1,%%xmm1 \n" - "packuswb %%xmm6,%%xmm6 \n" - "punpcklbw %%xmm6,%%xmm1 \n" - "movdqa %%xmm0,%%xmm6 \n" - "punpcklwd %%xmm1,%%xmm0 \n" - "punpckhwd %%xmm1,%%xmm6 \n" - "sub $0x8,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm6," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(matrix_argb) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBCOLORMATRIXROW_SSSE3 - -#ifdef HAS_ARGBQUANTIZEROW_SSE2 -// Quantize 4 ARGB pixels (16 bytes). -// aligned to 16 bytes -void ARGBQuantizeRow_SSE2(uint8* dst_argb, int scale, int interval_size, - int interval_offset, int width) { - asm volatile ( - "movd %2,%%xmm2 \n" - "movd %3,%%xmm3 \n" - "movd %4,%%xmm4 \n" - "pshuflw $0x40,%%xmm2,%%xmm2 \n" - "pshufd $0x44,%%xmm2,%%xmm2 \n" - "pshuflw $0x40,%%xmm3,%%xmm3 \n" - "pshufd $0x44,%%xmm3,%%xmm3 \n" - "pshuflw $0x40,%%xmm4,%%xmm4 \n" - "pshufd $0x44,%%xmm4,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "pslld $0x18,%%xmm6 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "pmulhuw %%xmm2,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm1 \n" - "punpckhbw %%xmm5,%%xmm1 \n" - "pmulhuw %%xmm2,%%xmm1 \n" - "pmullw %%xmm3,%%xmm0 \n" - "movdqa " MEMACCESS(0) ",%%xmm7 \n" - "pmullw %%xmm3,%%xmm1 \n" - "pand %%xmm6,%%xmm7 \n" - "paddw %%xmm4,%%xmm0 \n" - "paddw %%xmm4,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "por %%xmm7,%%xmm0 \n" - "sub $0x4,%1 \n" - "movdqa %%xmm0," MEMACCESS(0) " \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "jg 1b \n" - : "+r"(dst_argb), // %0 - "+r"(width) // %1 - : "r"(scale), // %2 - "r"(interval_size), // %3 - "r"(interval_offset) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBQUANTIZEROW_SSE2 - -#ifdef HAS_ARGBSHADEROW_SSE2 -// Shade 4 pixels at a time by specified value. -// Aligned to 16 bytes. -void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width, - uint32 value) { - asm volatile ( - "movd %3,%%xmm2 \n" - "punpcklbw %%xmm2,%%xmm2 \n" - "punpcklqdq %%xmm2,%%xmm2 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - "pmulhuw %%xmm2,%%xmm0 \n" - "pmulhuw %%xmm2,%%xmm1 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(value) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2" -#endif - ); -} -#endif // HAS_ARGBSHADEROW_SSE2 - -#ifdef HAS_ARGBMULTIPLYROW_SSE2 -// Multiply 2 rows of ARGB pixels together, 4 pixels at a time. -void ARGBMultiplyRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { - asm volatile ( - "pxor %%xmm5,%%xmm5 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqu " MEMACCESS(1) ",%%xmm2 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "movdqu %%xmm0,%%xmm1 \n" - "movdqu %%xmm2,%%xmm3 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "punpckhbw %%xmm5,%%xmm3 \n" - "pmulhuw %%xmm2,%%xmm0 \n" - "pmulhuw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(src_argb1), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} -#endif // HAS_ARGBMULTIPLYROW_SSE2 - -#ifdef HAS_ARGBADDROW_SSE2 -// Add 2 rows of ARGB pixels together, 4 pixels at a time. -void ARGBAddRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { - asm volatile ( - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(src_argb1), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_ARGBADDROW_SSE2 - -#ifdef HAS_ARGBSUBTRACTROW_SSE2 -// Subtract 2 rows of ARGB pixels, 4 pixels at a time. -void ARGBSubtractRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { - asm volatile ( - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "psubusb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_argb0), // %0 - "+r"(src_argb1), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_ARGBSUBTRACTROW_SSE2 - -#ifdef HAS_SOBELXROW_SSE2 -// SobelX as a matrix is -// -1 0 1 -// -2 0 2 -// -1 0 1 -void SobelXRow_SSE2(const uint8* src_y0, const uint8* src_y1, - const uint8* src_y2, uint8* dst_sobelx, int width) { - asm volatile ( - "sub %0,%1 \n" - "sub %0,%2 \n" - "sub %0,%3 \n" - "pxor %%xmm5,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - "movq " MEMACCESS2(0x2,0) ",%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm1 \n" - "psubw %%xmm1,%%xmm0 \n" - BUNDLEALIGN - MEMOPREG(movq,0x00,0,1,1,xmm1) // movq (%0,%1,1),%%xmm1 - MEMOPREG(movq,0x02,0,1,1,xmm2) // movq 0x2(%0,%1,1),%%xmm2 - "punpcklbw %%xmm5,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "psubw %%xmm2,%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movq,0x00,0,2,1,xmm2) // movq (%0,%2,1),%%xmm2 - MEMOPREG(movq,0x02,0,2,1,xmm3) // movq 0x2(%0,%2,1),%%xmm3 - "punpcklbw %%xmm5,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm3 \n" - "psubw %%xmm3,%%xmm2 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm1,%%xmm0 \n" - "paddw %%xmm1,%%xmm0 \n" - "pxor %%xmm1,%%xmm1 \n" - "psubw %%xmm0,%%xmm1 \n" - "pmaxsw %%xmm1,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "sub $0x8,%4 \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm0,0x00,0,3,1) // movq %%xmm0,(%0,%3,1) - "lea " MEMLEA(0x8,0) ",%0 \n" - "jg 1b \n" - : "+r"(src_y0), // %0 - "+r"(src_y1), // %1 - "+r"(src_y2), // %2 - "+r"(dst_sobelx), // %3 - "+r"(width) // %4 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} -#endif // HAS_SOBELXROW_SSE2 - -#ifdef HAS_SOBELYROW_SSE2 -// SobelY as a matrix is -// -1 -2 -1 -// 0 0 0 -// 1 2 1 -void SobelYRow_SSE2(const uint8* src_y0, const uint8* src_y1, - uint8* dst_sobely, int width) { - asm volatile ( - "sub %0,%1 \n" - "sub %0,%2 \n" - "pxor %%xmm5,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movq,0x00,0,1,1,xmm1) // movq (%0,%1,1),%%xmm1 - "punpcklbw %%xmm5,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm1 \n" - "psubw %%xmm1,%%xmm0 \n" - BUNDLEALIGN - "movq " MEMACCESS2(0x1,0) ",%%xmm1 \n" - MEMOPREG(movq,0x01,0,1,1,xmm2) // movq 0x1(%0,%1,1),%%xmm2 - "punpcklbw %%xmm5,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "psubw %%xmm2,%%xmm1 \n" - BUNDLEALIGN - "movq " MEMACCESS2(0x2,0) ",%%xmm2 \n" - MEMOPREG(movq,0x02,0,1,1,xmm3) // movq 0x2(%0,%1,1),%%xmm3 - "punpcklbw %%xmm5,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm3 \n" - "psubw %%xmm3,%%xmm2 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm1,%%xmm0 \n" - "paddw %%xmm1,%%xmm0 \n" - "pxor %%xmm1,%%xmm1 \n" - "psubw %%xmm0,%%xmm1 \n" - "pmaxsw %%xmm1,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "sub $0x8,%3 \n" - BUNDLEALIGN - MEMOPMEM(movq,xmm0,0x00,0,2,1) // movq %%xmm0,(%0,%2,1) - "lea " MEMLEA(0x8,0) ",%0 \n" - "jg 1b \n" - : "+r"(src_y0), // %0 - "+r"(src_y1), // %1 - "+r"(dst_sobely), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} -#endif // HAS_SOBELYROW_SSE2 - -#ifdef HAS_SOBELROW_SSE2 -// Adds Sobel X and Sobel Y and stores Sobel into ARGB. -// A = 255 -// R = Sobel -// G = Sobel -// B = Sobel -void SobelRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, - uint8* dst_argb, int width) { - asm volatile ( - "sub %0,%1 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pslld $0x18,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,0,1,1,xmm1) // movdqa (%0,%1,1),%%xmm1 - "lea " MEMLEA(0x10,0) ",%0 \n" - "paddusb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "punpcklbw %%xmm0,%%xmm2 \n" - "punpckhbw %%xmm0,%%xmm0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "punpcklwd %%xmm2,%%xmm1 \n" - "punpckhwd %%xmm2,%%xmm2 \n" - "por %%xmm5,%%xmm1 \n" - "por %%xmm5,%%xmm2 \n" - "movdqa %%xmm0,%%xmm3 \n" - "punpcklwd %%xmm0,%%xmm3 \n" - "punpckhwd %%xmm0,%%xmm0 \n" - "por %%xmm5,%%xmm3 \n" - "por %%xmm5,%%xmm0 \n" - "sub $0x10,%3 \n" - "movdqa %%xmm1," MEMACCESS(2) " \n" - "movdqa %%xmm2," MEMACCESS2(0x10,2) " \n" - "movdqa %%xmm3," MEMACCESS2(0x20,2) " \n" - "movdqa %%xmm0," MEMACCESS2(0x30,2) " \n" - "lea " MEMLEA(0x40,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_sobelx), // %0 - "+r"(src_sobely), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} -#endif // HAS_SOBELROW_SSE2 - -#ifdef HAS_SOBELTOPLANEROW_SSE2 -// Adds Sobel X and Sobel Y and stores Sobel into a plane. -void SobelToPlaneRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, - uint8* dst_y, int width) { - asm volatile ( - "sub %0,%1 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - "pslld $0x18,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,0,1,1,xmm1) // movdqa (%0,%1,1),%%xmm1 - "lea " MEMLEA(0x10,0) ",%0 \n" - "paddusb %%xmm1,%%xmm0 \n" - "sub $0x10,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_sobelx), // %0 - "+r"(src_sobely), // %1 - "+r"(dst_y), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} -#endif // HAS_SOBELTOPLANEROW_SSE2 - -#ifdef HAS_SOBELXYROW_SSE2 -// Mixes Sobel X, Sobel Y and Sobel into ARGB. -// A = 255 -// R = Sobel X -// G = Sobel -// B = Sobel Y -void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, - uint8* dst_argb, int width) { - asm volatile ( - "sub %0,%1 \n" - "pcmpeqb %%xmm5,%%xmm5 \n" - - // 8 pixel loop. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,0,1,1,xmm1) // movdqa (%0,%1,1),%%xmm1 - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "paddusb %%xmm1,%%xmm2 \n" - "movdqa %%xmm0,%%xmm3 \n" - "punpcklbw %%xmm5,%%xmm3 \n" - "punpckhbw %%xmm5,%%xmm0 \n" - "movdqa %%xmm1,%%xmm4 \n" - "punpcklbw %%xmm2,%%xmm4 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - "movdqa %%xmm4,%%xmm6 \n" - "punpcklwd %%xmm3,%%xmm6 \n" - "punpckhwd %%xmm3,%%xmm4 \n" - "movdqa %%xmm1,%%xmm7 \n" - "punpcklwd %%xmm0,%%xmm7 \n" - "punpckhwd %%xmm0,%%xmm1 \n" - "sub $0x10,%3 \n" - "movdqa %%xmm6," MEMACCESS(2) " \n" - "movdqa %%xmm4," MEMACCESS2(0x10,2) " \n" - "movdqa %%xmm7," MEMACCESS2(0x20,2) " \n" - "movdqa %%xmm1," MEMACCESS2(0x30,2) " \n" - "lea " MEMLEA(0x40,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_sobelx), // %0 - "+r"(src_sobely), // %1 - "+r"(dst_argb), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_SOBELXYROW_SSE2 - -#ifdef HAS_COMPUTECUMULATIVESUMROW_SSE2 -// Creates a table of cumulative sums where each value is a sum of all values -// above and to the left of the value, inclusive of the value. -void ComputeCumulativeSumRow_SSE2(const uint8* row, int32* cumsum, - const int32* previous_cumsum, int width) { - asm volatile ( - "pxor %%xmm0,%%xmm0 \n" - "pxor %%xmm1,%%xmm1 \n" - "sub $0x4,%3 \n" - "jl 49f \n" - "test $0xf,%1 \n" - "jne 49f \n" - - // 4 pixel loop \n" - LABELALIGN - "40: \n" - "movdqu " MEMACCESS(0) ",%%xmm2 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm2,%%xmm4 \n" - "punpcklbw %%xmm1,%%xmm2 \n" - "movdqa %%xmm2,%%xmm3 \n" - "punpcklwd %%xmm1,%%xmm2 \n" - "punpckhwd %%xmm1,%%xmm3 \n" - "punpckhbw %%xmm1,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "punpcklwd %%xmm1,%%xmm4 \n" - "punpckhwd %%xmm1,%%xmm5 \n" - "paddd %%xmm2,%%xmm0 \n" - "movdqa " MEMACCESS(2) ",%%xmm2 \n" - "paddd %%xmm0,%%xmm2 \n" - "paddd %%xmm3,%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,2) ",%%xmm3 \n" - "paddd %%xmm0,%%xmm3 \n" - "paddd %%xmm4,%%xmm0 \n" - "movdqa " MEMACCESS2(0x20,2) ",%%xmm4 \n" - "paddd %%xmm0,%%xmm4 \n" - "paddd %%xmm5,%%xmm0 \n" - "movdqa " MEMACCESS2(0x30,2) ",%%xmm5 \n" - "lea " MEMLEA(0x40,2) ",%2 \n" - "paddd %%xmm0,%%xmm5 \n" - "movdqa %%xmm2," MEMACCESS(1) " \n" - "movdqa %%xmm3," MEMACCESS2(0x10,1) " \n" - "movdqa %%xmm4," MEMACCESS2(0x20,1) " \n" - "movdqa %%xmm5," MEMACCESS2(0x30,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "sub $0x4,%3 \n" - "jge 40b \n" - - "49: \n" - "add $0x3,%3 \n" - "jl 19f \n" - - // 1 pixel loop \n" - LABELALIGN - "10: \n" - "movd " MEMACCESS(0) ",%%xmm2 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "punpcklbw %%xmm1,%%xmm2 \n" - "punpcklwd %%xmm1,%%xmm2 \n" - "paddd %%xmm2,%%xmm0 \n" - "movdqu " MEMACCESS(2) ",%%xmm2 \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "paddd %%xmm0,%%xmm2 \n" - "movdqu %%xmm2," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x1,%3 \n" - "jge 10b \n" - - "19: \n" - : "+r"(row), // %0 - "+r"(cumsum), // %1 - "+r"(previous_cumsum), // %2 - "+r"(width) // %3 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_COMPUTECUMULATIVESUMROW_SSE2 - -#ifdef HAS_CUMULATIVESUMTOAVERAGEROW_SSE2 -void CumulativeSumToAverageRow_SSE2(const int32* topleft, const int32* botleft, - int width, int area, uint8* dst, - int count) { - asm volatile ( - "movd %5,%%xmm5 \n" - "cvtdq2ps %%xmm5,%%xmm5 \n" - "rcpss %%xmm5,%%xmm4 \n" - "pshufd $0x0,%%xmm4,%%xmm4 \n" - "sub $0x4,%3 \n" - "jl 49f \n" - "cmpl $0x80,%5 \n" - "ja 40f \n" - - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrld $0x10,%%xmm6 \n" - "cvtdq2ps %%xmm6,%%xmm6 \n" - "addps %%xmm6,%%xmm5 \n" - "mulps %%xmm4,%%xmm5 \n" - "cvtps2dq %%xmm5,%%xmm5 \n" - "packssdw %%xmm5,%%xmm5 \n" - - // 4 pixel small loop \n" - LABELALIGN - "4: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - BUNDLEALIGN - MEMOPREG(psubd,0x00,0,4,4,xmm0) // psubd 0x00(%0,%4,4),%%xmm0 - MEMOPREG(psubd,0x10,0,4,4,xmm1) // psubd 0x10(%0,%4,4),%%xmm1 - MEMOPREG(psubd,0x20,0,4,4,xmm2) // psubd 0x20(%0,%4,4),%%xmm2 - MEMOPREG(psubd,0x30,0,4,4,xmm3) // psubd 0x30(%0,%4,4),%%xmm3 - "lea " MEMLEA(0x40,0) ",%0 \n" - "psubd " MEMACCESS(1) ",%%xmm0 \n" - "psubd " MEMACCESS2(0x10,1) ",%%xmm1 \n" - "psubd " MEMACCESS2(0x20,1) ",%%xmm2 \n" - "psubd " MEMACCESS2(0x30,1) ",%%xmm3 \n" - BUNDLEALIGN - MEMOPREG(paddd,0x00,1,4,4,xmm0) // paddd 0x00(%1,%4,4),%%xmm0 - MEMOPREG(paddd,0x10,1,4,4,xmm1) // paddd 0x10(%1,%4,4),%%xmm1 - MEMOPREG(paddd,0x20,1,4,4,xmm2) // paddd 0x20(%1,%4,4),%%xmm2 - MEMOPREG(paddd,0x30,1,4,4,xmm3) // paddd 0x30(%1,%4,4),%%xmm3 - "lea " MEMLEA(0x40,1) ",%1 \n" - "packssdw %%xmm1,%%xmm0 \n" - "packssdw %%xmm3,%%xmm2 \n" - "pmulhuw %%xmm5,%%xmm0 \n" - "pmulhuw %%xmm5,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "sub $0x4,%3 \n" - "jge 4b \n" - "jmp 49f \n" - - // 4 pixel loop \n" - LABELALIGN - "40: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "movdqa " MEMACCESS2(0x20,0) ",%%xmm2 \n" - "movdqa " MEMACCESS2(0x30,0) ",%%xmm3 \n" - BUNDLEALIGN - MEMOPREG(psubd,0x00,0,4,4,xmm0) // psubd 0x00(%0,%4,4),%%xmm0 - MEMOPREG(psubd,0x10,0,4,4,xmm1) // psubd 0x10(%0,%4,4),%%xmm1 - MEMOPREG(psubd,0x20,0,4,4,xmm2) // psubd 0x20(%0,%4,4),%%xmm2 - MEMOPREG(psubd,0x30,0,4,4,xmm3) // psubd 0x30(%0,%4,4),%%xmm3 - "lea " MEMLEA(0x40,0) ",%0 \n" - "psubd " MEMACCESS(1) ",%%xmm0 \n" - "psubd " MEMACCESS2(0x10,1) ",%%xmm1 \n" - "psubd " MEMACCESS2(0x20,1) ",%%xmm2 \n" - "psubd " MEMACCESS2(0x30,1) ",%%xmm3 \n" - BUNDLEALIGN - MEMOPREG(paddd,0x00,1,4,4,xmm0) // paddd 0x00(%1,%4,4),%%xmm0 - MEMOPREG(paddd,0x10,1,4,4,xmm1) // paddd 0x10(%1,%4,4),%%xmm1 - MEMOPREG(paddd,0x20,1,4,4,xmm2) // paddd 0x20(%1,%4,4),%%xmm2 - MEMOPREG(paddd,0x30,1,4,4,xmm3) // paddd 0x30(%1,%4,4),%%xmm3 - "lea " MEMLEA(0x40,1) ",%1 \n" - "cvtdq2ps %%xmm0,%%xmm0 \n" - "cvtdq2ps %%xmm1,%%xmm1 \n" - "mulps %%xmm4,%%xmm0 \n" - "mulps %%xmm4,%%xmm1 \n" - "cvtdq2ps %%xmm2,%%xmm2 \n" - "cvtdq2ps %%xmm3,%%xmm3 \n" - "mulps %%xmm4,%%xmm2 \n" - "mulps %%xmm4,%%xmm3 \n" - "cvtps2dq %%xmm0,%%xmm0 \n" - "cvtps2dq %%xmm1,%%xmm1 \n" - "cvtps2dq %%xmm2,%%xmm2 \n" - "cvtps2dq %%xmm3,%%xmm3 \n" - "packssdw %%xmm1,%%xmm0 \n" - "packssdw %%xmm3,%%xmm2 \n" - "packuswb %%xmm2,%%xmm0 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "sub $0x4,%3 \n" - "jge 40b \n" - - "49: \n" - "add $0x3,%3 \n" - "jl 19f \n" - - // 1 pixel loop \n" - LABELALIGN - "10: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(psubd,0x00,0,4,4,xmm0) // psubd 0x00(%0,%4,4),%%xmm0 - "lea " MEMLEA(0x10,0) ",%0 \n" - "psubd " MEMACCESS(1) ",%%xmm0 \n" - BUNDLEALIGN - MEMOPREG(paddd,0x00,1,4,4,xmm0) // paddd 0x00(%1,%4,4),%%xmm0 - "lea " MEMLEA(0x10,1) ",%1 \n" - "cvtdq2ps %%xmm0,%%xmm0 \n" - "mulps %%xmm4,%%xmm0 \n" - "cvtps2dq %%xmm0,%%xmm0 \n" - "packssdw %%xmm0,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x4,2) ",%2 \n" - "sub $0x1,%3 \n" - "jge 10b \n" - "19: \n" - : "+r"(topleft), // %0 - "+r"(botleft), // %1 - "+r"(dst), // %2 - "+rm"(count) // %3 - : "r"((intptr_t)(width)), // %4 - "rm"(area) // %5 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} -#endif // HAS_CUMULATIVESUMTOAVERAGEROW_SSE2 - -#ifdef HAS_ARGBAFFINEROW_SSE2 -// Copy ARGB pixels from source image with slope to a row of destination. -LIBYUV_API -void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, - uint8* dst_argb, const float* src_dudv, int width) { - intptr_t src_argb_stride_temp = src_argb_stride; - intptr_t temp = 0; - asm volatile ( - "movq " MEMACCESS(3) ",%%xmm2 \n" - "movq " MEMACCESS2(0x08,3) ",%%xmm7 \n" - "shl $0x10,%1 \n" - "add $0x4,%1 \n" - "movd %1,%%xmm5 \n" - "sub $0x4,%4 \n" - "jl 49f \n" - - "pshufd $0x44,%%xmm7,%%xmm7 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "movdqa %%xmm2,%%xmm0 \n" - "addps %%xmm7,%%xmm0 \n" - "movlhps %%xmm0,%%xmm2 \n" - "movdqa %%xmm7,%%xmm4 \n" - "addps %%xmm4,%%xmm4 \n" - "movdqa %%xmm2,%%xmm3 \n" - "addps %%xmm4,%%xmm3 \n" - "addps %%xmm4,%%xmm4 \n" - - // 4 pixel loop \n" - LABELALIGN - "40: \n" - "cvttps2dq %%xmm2,%%xmm0 \n" // x, y float to int first 2 - "cvttps2dq %%xmm3,%%xmm1 \n" // x, y float to int next 2 - "packssdw %%xmm1,%%xmm0 \n" // x, y as 8 shorts - "pmaddwd %%xmm5,%%xmm0 \n" // off = x * 4 + y * stride - "movd %%xmm0,%k1 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - "movd %%xmm0,%k5 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,0,1,1,xmm1) // movd (%0,%1,1),%%xmm1 - MEMOPREG(movd,0x00,0,5,1,xmm6) // movd (%0,%5,1),%%xmm6 - "punpckldq %%xmm6,%%xmm1 \n" - "addps %%xmm4,%%xmm2 \n" - "movq %%xmm1," MEMACCESS(2) " \n" - "movd %%xmm0,%k1 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - "movd %%xmm0,%k5 \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,0,1,1,xmm0) // movd (%0,%1,1),%%xmm0 - MEMOPREG(movd,0x00,0,5,1,xmm6) // movd (%0,%5,1),%%xmm6 - "punpckldq %%xmm6,%%xmm0 \n" - "addps %%xmm4,%%xmm3 \n" - "sub $0x4,%4 \n" - "movq %%xmm0," MEMACCESS2(0x08,2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jge 40b \n" - - "49: \n" - "add $0x3,%4 \n" - "jl 19f \n" - - // 1 pixel loop \n" - LABELALIGN - "10: \n" - "cvttps2dq %%xmm2,%%xmm0 \n" - "packssdw %%xmm0,%%xmm0 \n" - "pmaddwd %%xmm5,%%xmm0 \n" - "addps %%xmm7,%%xmm2 \n" - "movd %%xmm0,%k1 \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,0,1,1,xmm0) // movd (%0,%1,1),%%xmm0 - "sub $0x1,%4 \n" - "movd %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x04,2) ",%2 \n" - "jge 10b \n" - "19: \n" - : "+r"(src_argb), // %0 - "+r"(src_argb_stride_temp), // %1 - "+r"(dst_argb), // %2 - "+r"(src_dudv), // %3 - "+rm"(width), // %4 - "+r"(temp) // %5 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBAFFINEROW_SSE2 - -#ifdef HAS_INTERPOLATEROW_SSSE3 -// Bilinear filter 16x2 -> 16x1 -void InterpolateRow_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - asm volatile ( - "sub %1,%0 \n" - "shr %3 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x20,%3 \n" - "je 75f \n" - "cmp $0x40,%3 \n" - "je 50f \n" - "cmp $0x60,%3 \n" - "je 25f \n" - - "movd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x80,%3 \n" - "movd %3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "punpcklwd %%xmm5,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm2) - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm0 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - "pmaddubsw %%xmm5,%%xmm0 \n" - "pmaddubsw %%xmm5,%%xmm1 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 25 / 75. - LABELALIGN - "25: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm1) - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 25b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm1) - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 75 / 25. - LABELALIGN - "75: \n" - "movdqa " MEMACCESS(1) ",%%xmm1 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm0) - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 75b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - "sub $0x10,%2 \n" - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 100b \n" - - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t)(src_stride)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm5" -#endif - ); -} -#endif // HAS_INTERPOLATEROW_SSSE3 - -#ifdef HAS_INTERPOLATEROW_SSE2 -// Bilinear filter 16x2 -> 16x1 -void InterpolateRow_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - asm volatile ( - "sub %1,%0 \n" - "shr %3 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x20,%3 \n" - "je 75f \n" - "cmp $0x40,%3 \n" - "je 50f \n" - "cmp $0x60,%3 \n" - "je 25f \n" - - "movd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x80,%3 \n" - "movd %3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "punpcklwd %%xmm5,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm2) // movdqa (%1,%4,1),%%xmm2 - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm3 \n" - "punpcklbw %%xmm4,%%xmm2 \n" - "punpckhbw %%xmm4,%%xmm3 \n" - "punpcklbw %%xmm4,%%xmm0 \n" - "punpckhbw %%xmm4,%%xmm1 \n" - "psubw %%xmm0,%%xmm2 \n" - "psubw %%xmm1,%%xmm3 \n" - "paddw %%xmm2,%%xmm2 \n" - "paddw %%xmm3,%%xmm3 \n" - "pmulhw %%xmm5,%%xmm2 \n" - "pmulhw %%xmm5,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) // movdqa %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 25 / 75. - LABELALIGN - "25: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm1) // movdqa (%1,%4,1),%%xmm1 - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) // movdqa %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 25b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm1) // movdqa (%1,%4,1),%%xmm1 - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) // movdqa %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 75 / 25. - LABELALIGN - "75: \n" - "movdqa " MEMACCESS(1) ",%%xmm1 \n" - MEMOPREG(movdqa,0x00,1,4,1,xmm0) // movdqa (%1,%4,1),%%xmm0 - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) // movdqa %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 75b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - "sub $0x10,%2 \n" - MEMOPMEM(movdqa,xmm0,0x00,1,0,1) // movdqa %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 100b \n" - - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t)(src_stride)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_INTERPOLATEROW_SSE2 - -#ifdef HAS_INTERPOLATEROW_SSSE3 -// Bilinear filter 16x2 -> 16x1 -void InterpolateRow_Unaligned_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - asm volatile ( - "sub %1,%0 \n" - "shr %3 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x20,%3 \n" - "je 75f \n" - "cmp $0x40,%3 \n" - "je 50f \n" - "cmp $0x60,%3 \n" - "je 25f \n" - - "movd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x80,%3 \n" - "movd %3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "punpcklwd %%xmm5,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm2) - "movdqu %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm0 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - "pmaddubsw %%xmm5,%%xmm0 \n" - "pmaddubsw %%xmm5,%%xmm1 \n" - "psrlw $0x7,%%xmm0 \n" - "psrlw $0x7,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 25 / 75. - LABELALIGN - "25: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm1) - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 25b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm1) - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 75 / 25. - LABELALIGN - "75: \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm0) - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 75b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - "sub $0x10,%2 \n" - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 100b \n" - - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t)(src_stride)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm5" -#endif - ); -} -#endif // HAS_INTERPOLATEROW_SSSE3 - -#ifdef HAS_INTERPOLATEROW_SSE2 -// Bilinear filter 16x2 -> 16x1 -void InterpolateRow_Unaligned_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - asm volatile ( - "sub %1,%0 \n" - "shr %3 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x20,%3 \n" - "je 75f \n" - "cmp $0x40,%3 \n" - "je 50f \n" - "cmp $0x60,%3 \n" - "je 25f \n" - - "movd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x80,%3 \n" - "movd %3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "punpcklwd %%xmm5,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "pxor %%xmm4,%%xmm4 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm2) // movdqu (%1,%4,1),%%xmm2 - "movdqu %%xmm0,%%xmm1 \n" - "movdqu %%xmm2,%%xmm3 \n" - "punpcklbw %%xmm4,%%xmm2 \n" - "punpckhbw %%xmm4,%%xmm3 \n" - "punpcklbw %%xmm4,%%xmm0 \n" - "punpckhbw %%xmm4,%%xmm1 \n" - "psubw %%xmm0,%%xmm2 \n" - "psubw %%xmm1,%%xmm3 \n" - "paddw %%xmm2,%%xmm2 \n" - "paddw %%xmm3,%%xmm3 \n" - "pmulhw %%xmm5,%%xmm2 \n" - "pmulhw %%xmm5,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) // movdqu %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 25 / 75. - LABELALIGN - "25: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm1) // movdqu (%1,%4,1),%%xmm1 - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) // movdqu %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 25b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm1) // movdqu (%1,%4,1),%%xmm1 - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) // movdqu %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 75 / 25. - LABELALIGN - "75: \n" - "movdqu " MEMACCESS(1) ",%%xmm1 \n" - MEMOPREG(movdqu,0x00,1,4,1,xmm0) // movdqu (%1,%4,1),%%xmm0 - "pavgb %%xmm1,%%xmm0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "sub $0x10,%2 \n" - BUNDLEALIGN - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) // movdqu %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 75b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "movdqu " MEMACCESS(1) ",%%xmm0 \n" - "sub $0x10,%2 \n" - MEMOPMEM(movdqu,xmm0,0x00,1,0,1) // movdqu %%xmm0,(%1,%0,1) - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 100b \n" - - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t)(src_stride)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_INTERPOLATEROW_SSE2 - -#ifdef HAS_HALFROW_SSE2 -void HalfRow_SSE2(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { - asm volatile ( - "sub %0,%1 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(pavgb,0x00,0,3,1,xmm0) // pavgb (%0,%3),%%xmm0 - "sub $0x10,%2 \n" - MEMOPMEM(movdqa,xmm0,0x00,0,1,1) // movdqa %%xmm0,(%0,%1) - "lea " MEMLEA(0x10,0) ",%0 \n" - "jg 1b \n" - : "+r"(src_uv), // %0 - "+r"(dst_uv), // %1 - "+r"(pix) // %2 - : "r"((intptr_t)(src_uv_stride)) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0" -#endif - ); -} -#endif // HAS_HALFROW_SSE2 - -#ifdef HAS_ARGBTOBAYERROW_SSSE3 -void ARGBToBayerRow_SSSE3(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - asm volatile ( - // NaCL caveat - assumes movd is from GPR - "movd %3,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "pshufb %%xmm5,%%xmm1 \n" - "punpckldq %%xmm1,%%xmm0 \n" - "sub $0x8,%2 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : "g"(selector) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_ARGBTOBAYERROW_SSSE3 - -#ifdef HAS_ARGBTOBAYERGGROW_SSE2 -void ARGBToBayerGGRow_SSE2(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrld $0x18,%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrld $0x8,%%xmm0 \n" - "psrld $0x8,%%xmm1 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packssdw %%xmm1,%%xmm0 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x8,%2 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_bayer), // %1 - "+r"(pix) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_ARGBTOBAYERGGROW_SSE2 - -#ifdef HAS_ARGBSHUFFLEROW_SSSE3 -// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. -void ARGBShuffleRow_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { - asm volatile ( - "movdqa " MEMACCESS(3) ",%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "pshufb %%xmm5,%%xmm1 \n" - "sub $0x8,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : "r"(shuffler) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void ARGBShuffleRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { - asm volatile ( - "movdqa " MEMACCESS(3) ",%%xmm5 \n" - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "pshufb %%xmm5,%%xmm1 \n" - "sub $0x8,%2 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "movdqu %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : "r"(shuffler) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_ARGBSHUFFLEROW_SSSE3 - -#ifdef HAS_ARGBSHUFFLEROW_AVX2 -// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. -void ARGBShuffleRow_AVX2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { - asm volatile ( - "vbroadcastf128 " MEMACCESS(3) ",%%ymm5 \n" - LABELALIGN - "1: \n" - "vmovdqu " MEMACCESS(0) ",%%ymm0 \n" - "vmovdqu " MEMACCESS2(0x20,0) ",%%ymm1 \n" - "lea " MEMLEA(0x40,0) ",%0 \n" - "vpshufb %%ymm5,%%ymm0,%%ymm0 \n" - "vpshufb %%ymm5,%%ymm1,%%ymm1 \n" - "sub $0x10,%2 \n" - "vmovdqu %%ymm0," MEMACCESS(1) " \n" - "vmovdqu %%ymm1," MEMACCESS2(0x20,1) " \n" - "lea " MEMLEA(0x40,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(pix) // %2 - : "r"(shuffler) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_ARGBSHUFFLEROW_AVX2 - -#ifdef HAS_ARGBSHUFFLEROW_SSE2 -// For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. -void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { - uintptr_t pixel_temp = 0u; - asm volatile ( - "pxor %%xmm5,%%xmm5 \n" - "mov " MEMACCESS(4) ",%k2 \n" - "cmp $0x3000102,%k2 \n" - "je 3012f \n" - "cmp $0x10203,%k2 \n" - "je 123f \n" - "cmp $0x30201,%k2 \n" - "je 321f \n" - "cmp $0x2010003,%k2 \n" - "je 2103f \n" - - LABELALIGN - "1: \n" - "movzb " MEMACCESS(4) ",%2 \n" - MEMOPARG(movzb,0x00,0,2,1,2) " \n" // movzb (%0,%2,1),%2 - "mov %b2," MEMACCESS(1) " \n" - "movzb " MEMACCESS2(0x1,4) ",%2 \n" - MEMOPARG(movzb,0x00,0,2,1,2) " \n" // movzb (%0,%2,1),%2 - "mov %b2," MEMACCESS2(0x1,1) " \n" - BUNDLEALIGN - "movzb " MEMACCESS2(0x2,4) ",%2 \n" - MEMOPARG(movzb,0x00,0,2,1,2) " \n" // movzb (%0,%2,1),%2 - "mov %b2," MEMACCESS2(0x2,1) " \n" - "movzb " MEMACCESS2(0x3,4) ",%2 \n" - MEMOPARG(movzb,0x00,0,2,1,2) " \n" // movzb (%0,%2,1),%2 - "mov %b2," MEMACCESS2(0x3,1) " \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - "lea " MEMLEA(0x4,1) ",%1 \n" - "sub $0x1,%3 \n" - "jg 1b \n" - "jmp 99f \n" - - LABELALIGN - "123: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpckhbw %%xmm5,%%xmm1 \n" - "pshufhw $0x1b,%%xmm0,%%xmm0 \n" - "pshuflw $0x1b,%%xmm0,%%xmm0 \n" - "pshufhw $0x1b,%%xmm1,%%xmm1 \n" - "pshuflw $0x1b,%%xmm1,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 123b \n" - "jmp 99f \n" - - LABELALIGN - "321: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpckhbw %%xmm5,%%xmm1 \n" - "pshufhw $0x39,%%xmm0,%%xmm0 \n" - "pshuflw $0x39,%%xmm0,%%xmm0 \n" - "pshufhw $0x39,%%xmm1,%%xmm1 \n" - "pshuflw $0x39,%%xmm1,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 321b \n" - "jmp 99f \n" - - LABELALIGN - "2103: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpckhbw %%xmm5,%%xmm1 \n" - "pshufhw $0x93,%%xmm0,%%xmm0 \n" - "pshuflw $0x93,%%xmm0,%%xmm0 \n" - "pshufhw $0x93,%%xmm1,%%xmm1 \n" - "pshuflw $0x93,%%xmm1,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 2103b \n" - "jmp 99f \n" - - LABELALIGN - "3012: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpckhbw %%xmm5,%%xmm1 \n" - "pshufhw $0xc6,%%xmm0,%%xmm0 \n" - "pshuflw $0xc6,%%xmm0,%%xmm0 \n" - "pshufhw $0xc6,%%xmm1,%%xmm1 \n" - "pshuflw $0xc6,%%xmm1,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 3012b \n" - - "99: \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+d"(pixel_temp), // %2 - "+r"(pix) // %3 - : "r"(shuffler) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} -#endif // HAS_ARGBSHUFFLEROW_SSE2 - -#ifdef HAS_I422TOYUY2ROW_SSE2 -void I422ToYUY2Row_SSE2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_frame, int width) { - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movq " MEMACCESS(1) ",%%xmm2 \n" - MEMOPREG(movq,0x00,1,2,1,xmm3) // movq (%1,%2,1),%%xmm3 - "lea " MEMLEA(0x8,1) ",%1 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm0 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - "movdqu %%xmm0," MEMACCESS(3) " \n" - "movdqu %%xmm1," MEMACCESS2(0x10,3) " \n" - "lea " MEMLEA(0x20,3) ",%3 \n" - "sub $0x10,%4 \n" - "jg 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_frame), // %3 - "+rm"(width) // %4 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3" -#endif - ); -} -#endif // HAS_I422TOYUY2ROW_SSE2 - -#ifdef HAS_I422TOUYVYROW_SSE2 -void I422ToUYVYRow_SSE2(const uint8* src_y, - const uint8* src_u, - const uint8* src_v, - uint8* dst_frame, int width) { - asm volatile ( - "sub %1,%2 \n" - LABELALIGN - "1: \n" - "movq " MEMACCESS(1) ",%%xmm2 \n" - MEMOPREG(movq,0x00,1,2,1,xmm3) // movq (%1,%2,1),%%xmm3 - "lea " MEMLEA(0x8,1) ",%1 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "lea " MEMLEA(0x10,0) ",%0 \n" - "punpcklbw %%xmm0,%%xmm1 \n" - "punpckhbw %%xmm0,%%xmm2 \n" - "movdqu %%xmm1," MEMACCESS(3) " \n" - "movdqu %%xmm2," MEMACCESS2(0x10,3) " \n" - "lea " MEMLEA(0x20,3) ",%3 \n" - "sub $0x10,%4 \n" - "jg 1b \n" - : "+r"(src_y), // %0 - "+r"(src_u), // %1 - "+r"(src_v), // %2 - "+r"(dst_frame), // %3 - "+rm"(width) // %4 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3" -#endif - ); -} -#endif // HAS_I422TOUYVYROW_SSE2 - -#ifdef HAS_ARGBPOLYNOMIALROW_SSE2 -void ARGBPolynomialRow_SSE2(const uint8* src_argb, - uint8* dst_argb, const float* poly, - int width) { - asm volatile ( - "pxor %%xmm3,%%xmm3 \n" - - // 2 pixel loop. - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "punpcklbw %%xmm3,%%xmm0 \n" - "movdqa %%xmm0,%%xmm4 \n" - "punpcklwd %%xmm3,%%xmm0 \n" - "punpckhwd %%xmm3,%%xmm4 \n" - "cvtdq2ps %%xmm0,%%xmm0 \n" - "cvtdq2ps %%xmm4,%%xmm4 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm4,%%xmm5 \n" - "mulps " MEMACCESS2(0x10,3) ",%%xmm0 \n" - "mulps " MEMACCESS2(0x10,3) ",%%xmm4 \n" - "addps " MEMACCESS(3) ",%%xmm0 \n" - "addps " MEMACCESS(3) ",%%xmm4 \n" - "movdqa %%xmm1,%%xmm2 \n" - "movdqa %%xmm5,%%xmm6 \n" - "mulps %%xmm1,%%xmm2 \n" - "mulps %%xmm5,%%xmm6 \n" - "mulps %%xmm2,%%xmm1 \n" - "mulps %%xmm6,%%xmm5 \n" - "mulps " MEMACCESS2(0x20,3) ",%%xmm2 \n" - "mulps " MEMACCESS2(0x20,3) ",%%xmm6 \n" - "mulps " MEMACCESS2(0x30,3) ",%%xmm1 \n" - "mulps " MEMACCESS2(0x30,3) ",%%xmm5 \n" - "addps %%xmm2,%%xmm0 \n" - "addps %%xmm6,%%xmm4 \n" - "addps %%xmm1,%%xmm0 \n" - "addps %%xmm5,%%xmm4 \n" - "cvttps2dq %%xmm0,%%xmm0 \n" - "cvttps2dq %%xmm4,%%xmm4 \n" - "packuswb %%xmm4,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "sub $0x2,%2 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(poly) // %3 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} -#endif // HAS_ARGBPOLYNOMIALROW_SSE2 - -#ifdef HAS_ARGBPOLYNOMIALROW_AVX2 -void ARGBPolynomialRow_AVX2(const uint8* src_argb, - uint8* dst_argb, const float* poly, - int width) { - asm volatile ( - "vbroadcastf128 " MEMACCESS(3) ",%%ymm4 \n" - "vbroadcastf128 " MEMACCESS2(0x10,3) ",%%ymm5 \n" - "vbroadcastf128 " MEMACCESS2(0x20,3) ",%%ymm6 \n" - "vbroadcastf128 " MEMACCESS2(0x30,3) ",%%ymm7 \n" - - // 2 pixel loop. - LABELALIGN - "1: \n" - "vpmovzxbd " MEMACCESS(0) ",%%ymm0 \n" // 2 ARGB pixels - "lea " MEMLEA(0x8,0) ",%0 \n" - "vcvtdq2ps %%ymm0,%%ymm0 \n" // X 8 floats - "vmulps %%ymm0,%%ymm0,%%ymm2 \n" // X * X - "vmulps %%ymm7,%%ymm0,%%ymm3 \n" // C3 * X - "vfmadd132ps %%ymm5,%%ymm4,%%ymm0 \n" // result = C0 + C1 * X - "vfmadd231ps %%ymm6,%%ymm2,%%ymm0 \n" // result += C2 * X * X - "vfmadd231ps %%ymm3,%%ymm2,%%ymm0 \n" // result += C3 * X * X * X - "vcvttps2dq %%ymm0,%%ymm0 \n" - "vpackusdw %%ymm0,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vpackuswb %%xmm0,%%xmm0,%%xmm0 \n" - "sub $0x2,%2 \n" - "vmovq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(width) // %2 - : "r"(poly) // %3 - : "memory", "cc" -#if defined(__SSE2__) -// TODO(fbarchard): declare ymm usage when applicable. - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} -#endif // HAS_ARGBPOLYNOMIALROW_AVX2 - -#ifdef HAS_ARGBCOLORTABLEROW_X86 -// Tranform ARGB pixels with color table. -void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, - int width) { - uintptr_t pixel_temp = 0u; - asm volatile ( - // 1 pixel loop. - LABELALIGN - "1: \n" - "movzb " MEMACCESS(0) ",%1 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - MEMOPARG(movzb,0x00,3,1,4,1) " \n" // movzb (%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x4,0) " \n" - "movzb " MEMACCESS2(-0x3,0) ",%1 \n" - MEMOPARG(movzb,0x01,3,1,4,1) " \n" // movzb 0x1(%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x3,0) " \n" - "movzb " MEMACCESS2(-0x2,0) ",%1 \n" - MEMOPARG(movzb,0x02,3,1,4,1) " \n" // movzb 0x2(%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x2,0) " \n" - "movzb " MEMACCESS2(-0x1,0) ",%1 \n" - MEMOPARG(movzb,0x03,3,1,4,1) " \n" // movzb 0x3(%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x1,0) " \n" - "dec %2 \n" - "jg 1b \n" - : "+r"(dst_argb), // %0 - "+d"(pixel_temp), // %1 - "+r"(width) // %2 - : "r"(table_argb) // %3 - : "memory", "cc"); -} -#endif // HAS_ARGBCOLORTABLEROW_X86 - -#ifdef HAS_RGBCOLORTABLEROW_X86 -// Tranform RGB pixels with color table. -void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { - uintptr_t pixel_temp = 0u; - asm volatile ( - // 1 pixel loop. - LABELALIGN - "1: \n" - "movzb " MEMACCESS(0) ",%1 \n" - "lea " MEMLEA(0x4,0) ",%0 \n" - MEMOPARG(movzb,0x00,3,1,4,1) " \n" // movzb (%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x4,0) " \n" - "movzb " MEMACCESS2(-0x3,0) ",%1 \n" - MEMOPARG(movzb,0x01,3,1,4,1) " \n" // movzb 0x1(%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x3,0) " \n" - "movzb " MEMACCESS2(-0x2,0) ",%1 \n" - MEMOPARG(movzb,0x02,3,1,4,1) " \n" // movzb 0x2(%3,%1,4),%1 - "mov %b1," MEMACCESS2(-0x2,0) " \n" - "dec %2 \n" - "jg 1b \n" - : "+r"(dst_argb), // %0 - "+d"(pixel_temp), // %1 - "+r"(width) // %2 - : "r"(table_argb) // %3 - : "memory", "cc"); -} -#endif // HAS_RGBCOLORTABLEROW_X86 - -#ifdef HAS_ARGBLUMACOLORTABLEROW_SSSE3 -// Tranform RGB pixels with luma table. -void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, uint8* dst_argb, - int width, - const uint8* luma, uint32 lumacoeff) { - uintptr_t pixel_temp = 0u; - uintptr_t table_temp = 0u; - asm volatile ( - "movd %6,%%xmm3 \n" - "pshufd $0x0,%%xmm3,%%xmm3 \n" - "pcmpeqb %%xmm4,%%xmm4 \n" - "psllw $0x8,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - - // 4 pixel loop. - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(2) ",%%xmm0 \n" - "pmaddubsw %%xmm3,%%xmm0 \n" - "phaddw %%xmm0,%%xmm0 \n" - "pand %%xmm4,%%xmm0 \n" - "punpcklwd %%xmm5,%%xmm0 \n" - "movd %%xmm0,%k1 \n" // 32 bit offset - "add %5,%1 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - - "movzb " MEMACCESS(2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS(3) " \n" - "movzb " MEMACCESS2(0x1,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x1,3) " \n" - "movzb " MEMACCESS2(0x2,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x2,3) " \n" - "movzb " MEMACCESS2(0x3,2) ",%0 \n" - "mov %b0," MEMACCESS2(0x3,3) " \n" - - "movd %%xmm0,%k1 \n" // 32 bit offset - "add %5,%1 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - - "movzb " MEMACCESS2(0x4,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x4,3) " \n" - BUNDLEALIGN - "movzb " MEMACCESS2(0x5,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x5,3) " \n" - "movzb " MEMACCESS2(0x6,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x6,3) " \n" - "movzb " MEMACCESS2(0x7,2) ",%0 \n" - "mov %b0," MEMACCESS2(0x7,3) " \n" - - "movd %%xmm0,%k1 \n" // 32 bit offset - "add %5,%1 \n" - "pshufd $0x39,%%xmm0,%%xmm0 \n" - - "movzb " MEMACCESS2(0x8,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x8,3) " \n" - "movzb " MEMACCESS2(0x9,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0x9,3) " \n" - "movzb " MEMACCESS2(0xa,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0xa,3) " \n" - "movzb " MEMACCESS2(0xb,2) ",%0 \n" - "mov %b0," MEMACCESS2(0xb,3) " \n" - - "movd %%xmm0,%k1 \n" // 32 bit offset - "add %5,%1 \n" - - "movzb " MEMACCESS2(0xc,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0xc,3) " \n" - "movzb " MEMACCESS2(0xd,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0xd,3) " \n" - "movzb " MEMACCESS2(0xe,2) ",%0 \n" - MEMOPARG(movzb,0x00,1,0,1,0) " \n" // movzb (%1,%0,1),%0 - "mov %b0," MEMACCESS2(0xe,3) " \n" - "movzb " MEMACCESS2(0xf,2) ",%0 \n" - "mov %b0," MEMACCESS2(0xf,3) " \n" - "sub $0x4,%4 \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "lea " MEMLEA(0x10,3) ",%3 \n" - "jg 1b \n" - : "+d"(pixel_temp), // %0 - "+a"(table_temp), // %1 - "+r"(src_argb), // %2 - "+r"(dst_argb), // %3 - "+rm"(width) // %4 - : "r"(luma), // %5 - "rm"(lumacoeff) // %6 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm3", "xmm4", "xmm5" -#endif - ); -} -#endif // HAS_ARGBLUMACOLORTABLEROW_SSSE3 - -#endif // defined(__x86_64__) || defined(__i386__) - -#ifdef __cplusplus -} // extern "C" -} // namespace libyuv -#endif diff --git a/TMessagesProj/jni/libyuv/source/row_win.cc b/TMessagesProj/jni/libyuv/source/row_win.cc index f58fc513..5cb5d1e4 100644 --- a/TMessagesProj/jni/libyuv/source/row_win.cc +++ b/TMessagesProj/jni/libyuv/source/row_win.cc @@ -10,7 +10,8 @@ #include "libyuv/row.h" -#if defined (_M_X64) && !defined(LIBYUV_DISABLE_X86) && defined(_MSC_VER) +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_X64) && \ + defined(_MSC_VER) && !defined(__clang__) #include #include // For _mm_maddubs_epi16 #endif @@ -20,166 +21,110 @@ namespace libyuv { extern "C" { #endif -// This module is for Visual C. -#if !defined(LIBYUV_DISABLE_X86) && defined(_MSC_VER) - -#define YG 74 /* (int8)(1.164 * 64 + 0.5) */ - -#define UB 127 /* min(127,(int8)(2.018 * 64)) */ -#define UG -25 /* (int8)(-0.391 * 64 - 0.5) */ -#define UR 0 - -#define VB 0 -#define VG -52 /* (int8)(-0.813 * 64 - 0.5) */ -#define VR 102 /* (int8)(1.596 * 64 + 0.5) */ - -// Bias -#define BB UB * 128 + VB * 128 -#define BG UG * 128 + VG * 128 -#define BR UR * 128 + VR * 128 - -static const vec8 kUVToB = { - UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB -}; - -static const vec8 kUVToR = { - UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR -}; - -static const vec8 kUVToG = { - UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG -}; - -static const vec8 kVUToB = { - VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, -}; - -static const vec8 kVUToR = { - VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, -}; - -static const vec8 kVUToG = { - VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, -}; - -static const vec16 kYToRgb = { YG, YG, YG, YG, YG, YG, YG, YG }; -static const vec16 kYSub16 = { 16, 16, 16, 16, 16, 16, 16, 16 }; -static const vec16 kUVBiasB = { BB, BB, BB, BB, BB, BB, BB, BB }; -static const vec16 kUVBiasG = { BG, BG, BG, BG, BG, BG, BG, BG }; -static const vec16 kUVBiasR = { BR, BR, BR, BR, BR, BR, BR, BR }; +// This module is for Visual C 32/64 bit and clangcl 32 bit +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || (defined(_M_X64) && !defined(__clang__))) // 64 bit #if defined(_M_X64) -// Aligned destination version. -__declspec(align(16)) +// Read 4 UV from 422, upsample to 8 UV. +#define READYUV422 \ + xmm0 = _mm_cvtsi32_si128(*(uint32*)u_buf); \ + xmm1 = _mm_cvtsi32_si128(*(uint32*)(u_buf + offset)); \ + xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); \ + xmm0 = _mm_unpacklo_epi16(xmm0, xmm0); \ + u_buf += 4; \ + xmm4 = _mm_loadl_epi64((__m128i*)y_buf); \ + xmm4 = _mm_unpacklo_epi8(xmm4, xmm4); \ + y_buf += 8; + +// Read 4 UV from 422, upsample to 8 UV. With 8 Alpha. +#define READYUVA422 \ + xmm0 = _mm_cvtsi32_si128(*(uint32*)u_buf); \ + xmm1 = _mm_cvtsi32_si128(*(uint32*)(u_buf + offset)); \ + xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); \ + xmm0 = _mm_unpacklo_epi16(xmm0, xmm0); \ + u_buf += 4; \ + xmm4 = _mm_loadl_epi64((__m128i*)y_buf); \ + xmm4 = _mm_unpacklo_epi8(xmm4, xmm4); \ + y_buf += 8; \ + xmm5 = _mm_loadl_epi64((__m128i*)a_buf); \ + a_buf += 8; + +// Convert 8 pixels: 8 UV and 8 Y. +#define YUVTORGB(yuvconstants) \ + xmm1 = _mm_loadu_si128(&xmm0); \ + xmm2 = _mm_loadu_si128(&xmm0); \ + xmm0 = _mm_maddubs_epi16(xmm0, *(__m128i*)yuvconstants->kUVToB); \ + xmm1 = _mm_maddubs_epi16(xmm1, *(__m128i*)yuvconstants->kUVToG); \ + xmm2 = _mm_maddubs_epi16(xmm2, *(__m128i*)yuvconstants->kUVToR); \ + xmm0 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasB, xmm0); \ + xmm1 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasG, xmm1); \ + xmm2 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasR, xmm2); \ + xmm4 = _mm_mulhi_epu16(xmm4, *(__m128i*)yuvconstants->kYToRgb); \ + xmm0 = _mm_adds_epi16(xmm0, xmm4); \ + xmm1 = _mm_adds_epi16(xmm1, xmm4); \ + xmm2 = _mm_adds_epi16(xmm2, xmm4); \ + xmm0 = _mm_srai_epi16(xmm0, 6); \ + xmm1 = _mm_srai_epi16(xmm1, 6); \ + xmm2 = _mm_srai_epi16(xmm2, 6); \ + xmm0 = _mm_packus_epi16(xmm0, xmm0); \ + xmm1 = _mm_packus_epi16(xmm1, xmm1); \ + xmm2 = _mm_packus_epi16(xmm2, xmm2); + +// Store 8 ARGB values. +#define STOREARGB \ + xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); \ + xmm2 = _mm_unpacklo_epi8(xmm2, xmm5); \ + xmm1 = _mm_loadu_si128(&xmm0); \ + xmm0 = _mm_unpacklo_epi16(xmm0, xmm2); \ + xmm1 = _mm_unpackhi_epi16(xmm1, xmm2); \ + _mm_storeu_si128((__m128i *)dst_argb, xmm0); \ + _mm_storeu_si128((__m128i *)(dst_argb + 16), xmm1); \ + dst_argb += 32; + + +#if defined(HAS_I422TOARGBROW_SSSE3) void I422ToARGBRow_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { - __m128i xmm0, xmm1, xmm2, xmm3; + __m128i xmm0, xmm1, xmm2, xmm4; const __m128i xmm5 = _mm_set1_epi8(-1); - const __m128i xmm4 = _mm_setzero_si128(); const ptrdiff_t offset = (uint8*)v_buf - (uint8*)u_buf; - while (width > 0) { - xmm0 = _mm_cvtsi32_si128(*(uint32*)u_buf); - xmm1 = _mm_cvtsi32_si128(*(uint32*)(u_buf + offset)); - xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); - xmm0 = _mm_unpacklo_epi16(xmm0, xmm0); - xmm1 = _mm_load_si128(&xmm0); - xmm2 = _mm_load_si128(&xmm0); - xmm0 = _mm_maddubs_epi16(xmm0, *(__m128i*)kUVToB); - xmm1 = _mm_maddubs_epi16(xmm1, *(__m128i*)kUVToG); - xmm2 = _mm_maddubs_epi16(xmm2, *(__m128i*)kUVToR); - xmm0 = _mm_sub_epi16(xmm0, *(__m128i*)kUVBiasB); - xmm1 = _mm_sub_epi16(xmm1, *(__m128i*)kUVBiasG); - xmm2 = _mm_sub_epi16(xmm2, *(__m128i*)kUVBiasR); - xmm3 = _mm_loadl_epi64((__m128i*)y_buf); - xmm3 = _mm_unpacklo_epi8(xmm3, xmm4); - xmm3 = _mm_subs_epi16(xmm3, *(__m128i*)kYSub16); - xmm3 = _mm_mullo_epi16(xmm3, *(__m128i*)kYToRgb); - xmm0 = _mm_adds_epi16(xmm0, xmm3); - xmm1 = _mm_adds_epi16(xmm1, xmm3); - xmm2 = _mm_adds_epi16(xmm2, xmm3); - xmm0 = _mm_srai_epi16(xmm0, 6); - xmm1 = _mm_srai_epi16(xmm1, 6); - xmm2 = _mm_srai_epi16(xmm2, 6); - xmm0 = _mm_packus_epi16(xmm0, xmm0); - xmm1 = _mm_packus_epi16(xmm1, xmm1); - xmm2 = _mm_packus_epi16(xmm2, xmm2); - xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); - xmm2 = _mm_unpacklo_epi8(xmm2, xmm5); - xmm1 = _mm_load_si128(&xmm0); - xmm0 = _mm_unpacklo_epi16(xmm0, xmm2); - xmm1 = _mm_unpackhi_epi16(xmm1, xmm2); - - _mm_store_si128((__m128i *)dst_argb, xmm0); - _mm_store_si128((__m128i *)(dst_argb + 16), xmm1); - - y_buf += 8; - u_buf += 4; - dst_argb += 32; + READYUV422 + YUVTORGB(yuvconstants) + STOREARGB width -= 8; } } +#endif -// Unaligned destination version. -void I422ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - __m128i xmm0, xmm1, xmm2, xmm3; - const __m128i xmm5 = _mm_set1_epi8(-1); - const __m128i xmm4 = _mm_setzero_si128(); +#if defined(HAS_I422ALPHATOARGBROW_SSSE3) +void I422AlphaToARGBRow_SSSE3(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __m128i xmm0, xmm1, xmm2, xmm4, xmm5; const ptrdiff_t offset = (uint8*)v_buf - (uint8*)u_buf; - while (width > 0) { - xmm0 = _mm_cvtsi32_si128(*(uint32*)u_buf); - xmm1 = _mm_cvtsi32_si128(*(uint32*)(u_buf + offset)); - xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); - xmm0 = _mm_unpacklo_epi16(xmm0, xmm0); - xmm1 = _mm_load_si128(&xmm0); - xmm2 = _mm_load_si128(&xmm0); - xmm0 = _mm_maddubs_epi16(xmm0, *(__m128i*)kUVToB); - xmm1 = _mm_maddubs_epi16(xmm1, *(__m128i*)kUVToG); - xmm2 = _mm_maddubs_epi16(xmm2, *(__m128i*)kUVToR); - xmm0 = _mm_sub_epi16(xmm0, *(__m128i*)kUVBiasB); - xmm1 = _mm_sub_epi16(xmm1, *(__m128i*)kUVBiasG); - xmm2 = _mm_sub_epi16(xmm2, *(__m128i*)kUVBiasR); - xmm3 = _mm_loadl_epi64((__m128i*)y_buf); - xmm3 = _mm_unpacklo_epi8(xmm3, xmm4); - xmm3 = _mm_subs_epi16(xmm3, *(__m128i*)kYSub16); - xmm3 = _mm_mullo_epi16(xmm3, *(__m128i*)kYToRgb); - xmm0 = _mm_adds_epi16(xmm0, xmm3); - xmm1 = _mm_adds_epi16(xmm1, xmm3); - xmm2 = _mm_adds_epi16(xmm2, xmm3); - xmm0 = _mm_srai_epi16(xmm0, 6); - xmm1 = _mm_srai_epi16(xmm1, 6); - xmm2 = _mm_srai_epi16(xmm2, 6); - xmm0 = _mm_packus_epi16(xmm0, xmm0); - xmm1 = _mm_packus_epi16(xmm1, xmm1); - xmm2 = _mm_packus_epi16(xmm2, xmm2); - xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); - xmm2 = _mm_unpacklo_epi8(xmm2, xmm5); - xmm1 = _mm_load_si128(&xmm0); - xmm0 = _mm_unpacklo_epi16(xmm0, xmm2); - xmm1 = _mm_unpackhi_epi16(xmm1, xmm2); - - _mm_storeu_si128((__m128i *)dst_argb, xmm0); - _mm_storeu_si128((__m128i *)(dst_argb + 16), xmm1); - - y_buf += 8; - u_buf += 4; - dst_argb += 32; + READYUVA422 + YUVTORGB(yuvconstants) + STOREARGB width -= 8; } } +#endif + // 32 bit #else // defined(_M_X64) - #ifdef HAS_ARGBTOYROW_SSSE3 // Constants for ARGB. @@ -208,15 +153,10 @@ static const vec8 kARGBToVJ = { -20, -107, 127, 0, -20, -107, 127, 0, -20, -107, 127, 0, -20, -107, 127, 0 }; -// vpermd for vphaddw + vpackuswb vpermd. -static const lvec32 kPermdARGBToY_AVX = { - 0, 4, 1, 5, 2, 6, 3, 7 -}; - // vpshufb for vphaddw + vpackuswb packed to shorts. static const lvec8 kShufARGBToUV_AVX = { 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15, - 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15, + 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15 }; // Constants for BGRA. @@ -262,6 +202,7 @@ static const uvec8 kAddY16 = { 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u }; +// 7 bit fixed point 0.5. static const vec16 kAddYJ64 = { 64, 64, 64, 64, 64, 64, 64, 64 }; @@ -285,6 +226,24 @@ static const uvec8 kShuffleMaskRAWToARGB = { 2u, 1u, 0u, 12u, 5u, 4u, 3u, 13u, 8u, 7u, 6u, 14u, 11u, 10u, 9u, 15u }; +// Shuffle table for converting RAW to RGB24. First 8. +static const uvec8 kShuffleMaskRAWToRGB24_0 = { + 2u, 1u, 0u, 5u, 4u, 3u, 8u, 7u, + 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u +}; + +// Shuffle table for converting RAW to RGB24. Middle 8. +static const uvec8 kShuffleMaskRAWToRGB24_1 = { + 2u, 7u, 6u, 5u, 10u, 9u, 8u, 13u, + 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u +}; + +// Shuffle table for converting RAW to RGB24. Last 8. +static const uvec8 kShuffleMaskRAWToRGB24_2 = { + 8u, 7u, 12u, 11u, 10u, 15u, 14u, 13u, + 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u +}; + // Shuffle table for converting ARGB to RGB24. static const uvec8 kShuffleMaskARGBToRGB24 = { 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u @@ -300,51 +259,46 @@ static const uvec8 kShuffleMaskARGBToRGB24_0 = { 0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 128u, 128u, 128u, 128u, 10u, 12u, 13u, 14u }; -// Shuffle table for converting ARGB to RAW. -static const uvec8 kShuffleMaskARGBToRAW_0 = { - 2u, 1u, 0u, 6u, 5u, 4u, 10u, 9u, 128u, 128u, 128u, 128u, 8u, 14u, 13u, 12u +// YUY2 shuf 16 Y to 32 Y. +static const lvec8 kShuffleYUY2Y = { + 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, + 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14 +}; + +// YUY2 shuf 8 UV to 16 UV. +static const lvec8 kShuffleYUY2UV = { + 1, 3, 1, 3, 5, 7, 5, 7, 9, 11, 9, 11, 13, 15, 13, 15, + 1, 3, 1, 3, 5, 7, 5, 7, 9, 11, 9, 11, 13, 15, 13, 15 +}; + +// UYVY shuf 16 Y to 32 Y. +static const lvec8 kShuffleUYVYY = { + 1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, + 1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15 +}; + +// UYVY shuf 8 UV to 16 UV. +static const lvec8 kShuffleUYVYUV = { + 0, 2, 0, 2, 4, 6, 4, 6, 8, 10, 8, 10, 12, 14, 12, 14, + 0, 2, 0, 2, 4, 6, 4, 6, 8, 10, 8, 10, 12, 14, 12, 14 +}; + +// NV21 shuf 8 VU to 16 UV. +static const lvec8 kShuffleNV21 = { + 1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6, + 1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6, }; // Duplicates gray value 3 times and fills in alpha opaque. -__declspec(naked) __declspec(align(16)) -void I400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int pix) { +__declspec(naked) +void J400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] // src_y mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm5, xmm5 // generate mask 0xff000000 pslld xmm5, 24 - align 4 - convertloop: - movq xmm0, qword ptr [eax] - lea eax, [eax + 8] - punpcklbw xmm0, xmm0 - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm0 - punpckhwd xmm1, xmm1 - por xmm0, xmm5 - por xmm1, xmm5 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void I400ToARGBRow_Unaligned_SSE2(const uint8* src_y, uint8* dst_argb, - int pix) { - __asm { - mov eax, [esp + 4] // src_y - mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix - pcmpeqb xmm5, xmm5 // generate mask 0xff000000 - pslld xmm5, 24 - - align 4 convertloop: movq xmm0, qword ptr [eax] lea eax, [eax + 8] @@ -363,17 +317,48 @@ void I400ToARGBRow_Unaligned_SSE2(const uint8* src_y, uint8* dst_argb, } } -__declspec(naked) __declspec(align(16)) -void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix) { +#ifdef HAS_J400TOARGBROW_AVX2 +// Duplicates gray value 3 times and fills in alpha opaque. +__declspec(naked) +void J400ToARGBRow_AVX2(const uint8* src_y, uint8* dst_argb, int width) { + __asm { + mov eax, [esp + 4] // src_y + mov edx, [esp + 8] // dst_argb + mov ecx, [esp + 12] // width + vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0xff000000 + vpslld ymm5, ymm5, 24 + + convertloop: + vmovdqu xmm0, [eax] + lea eax, [eax + 16] + vpermq ymm0, ymm0, 0xd8 + vpunpcklbw ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 + vpunpckhwd ymm1, ymm0, ymm0 + vpunpcklwd ymm0, ymm0, ymm0 + vpor ymm0, ymm0, ymm5 + vpor ymm1, ymm1, ymm5 + vmovdqu [edx], ymm0 + vmovdqu [edx + 32], ymm1 + lea edx, [edx + 64] + sub ecx, 16 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_J400TOARGBROW_AVX2 + +__declspec(naked) +void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] // src_rgb24 mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm5, xmm5 // generate mask 0xff000000 pslld xmm5, 24 - movdqa xmm4, kShuffleMaskRGB24ToARGB + movdqa xmm4, xmmword ptr kShuffleMaskRGB24ToARGB - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -385,35 +370,34 @@ void RGB24ToARGBRow_SSSE3(const uint8* src_rgb24, uint8* dst_argb, int pix) { por xmm2, xmm5 palignr xmm1, xmm0, 12 // xmm1 = { xmm3[0:7] xmm0[12:15]} pshufb xmm0, xmm4 - movdqa [edx + 32], xmm2 + movdqu [edx + 32], xmm2 por xmm0, xmm5 pshufb xmm1, xmm4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 por xmm1, xmm5 palignr xmm3, xmm3, 4 // xmm3 = { xmm3[4:15]} pshufb xmm3, xmm4 - movdqa [edx + 16], xmm1 + movdqu [edx + 16], xmm1 por xmm3, xmm5 - sub ecx, 16 - movdqa [edx + 48], xmm3 + movdqu [edx + 48], xmm3 lea edx, [edx + 64] + sub ecx, 16 jg convertloop ret } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, - int pix) { + int width) { __asm { mov eax, [esp + 4] // src_raw mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm5, xmm5 // generate mask 0xff000000 pslld xmm5, 24 - movdqa xmm4, kShuffleMaskRAWToARGB + movdqa xmm4, xmmword ptr kShuffleMaskRAWToARGB - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -425,18 +409,46 @@ void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, por xmm2, xmm5 palignr xmm1, xmm0, 12 // xmm1 = { xmm3[0:7] xmm0[12:15]} pshufb xmm0, xmm4 - movdqa [edx + 32], xmm2 + movdqu [edx + 32], xmm2 por xmm0, xmm5 pshufb xmm1, xmm4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 por xmm1, xmm5 palignr xmm3, xmm3, 4 // xmm3 = { xmm3[4:15]} pshufb xmm3, xmm4 - movdqa [edx + 16], xmm1 + movdqu [edx + 16], xmm1 por xmm3, xmm5 - sub ecx, 16 - movdqa [edx + 48], xmm3 + movdqu [edx + 48], xmm3 lea edx, [edx + 64] + sub ecx, 16 + jg convertloop + ret + } +} + +__declspec(naked) +void RAWToRGB24Row_SSSE3(const uint8* src_raw, uint8* dst_rgb24, int width) { + __asm { + mov eax, [esp + 4] // src_raw + mov edx, [esp + 8] // dst_rgb24 + mov ecx, [esp + 12] // width + movdqa xmm3, xmmword ptr kShuffleMaskRAWToRGB24_0 + movdqa xmm4, xmmword ptr kShuffleMaskRAWToRGB24_1 + movdqa xmm5, xmmword ptr kShuffleMaskRAWToRGB24_2 + + convertloop: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 4] + movdqu xmm2, [eax + 8] + lea eax, [eax + 24] + pshufb xmm0, xmm3 + pshufb xmm1, xmm4 + pshufb xmm2, xmm5 + movq qword ptr [edx], xmm0 + movq qword ptr [edx + 8], xmm1 + movq qword ptr [edx + 16], xmm2 + lea edx, [edx + 24] + sub ecx, 8 jg convertloop ret } @@ -449,9 +461,9 @@ void RAWToARGBRow_SSSE3(const uint8* src_raw, uint8* dst_argb, // v * (256 + 8) // G shift of 5 is incorporated, so shift is 5 + 8 and 5 + 3 // 20 instructions. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, - int pix) { + int width) { __asm { mov eax, 0x01080108 // generate multiplier to repeat 5 bits movd xmm5, eax @@ -469,11 +481,10 @@ void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, mov eax, [esp + 4] // src_rgb565 mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width sub edx, eax sub edx, eax - align 4 convertloop: movdqu xmm0, [eax] // fetch 8 pixels of bgr565 movdqa xmm1, xmm0 @@ -490,8 +501,8 @@ void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, movdqa xmm2, xmm1 punpcklbw xmm1, xmm0 punpckhbw xmm2, xmm0 - movdqa [eax * 2 + edx], xmm1 // store 4 pixels of ARGB - movdqa [eax * 2 + edx + 16], xmm2 // store next 4 pixels of ARGB + movdqu [eax * 2 + edx], xmm1 // store 4 pixels of ARGB + movdqu [eax * 2 + edx + 16], xmm2 // store next 4 pixels of ARGB lea eax, [eax + 16] sub ecx, 8 jg convertloop @@ -499,10 +510,157 @@ void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb, } } +#ifdef HAS_RGB565TOARGBROW_AVX2 +// pmul method to replicate bits. +// Math to replicate bits: +// (v << 8) | (v << 3) +// v * 256 + v * 8 +// v * (256 + 8) +// G shift of 5 is incorporated, so shift is 5 + 8 and 5 + 3 +__declspec(naked) +void RGB565ToARGBRow_AVX2(const uint8* src_rgb565, uint8* dst_argb, + int width) { + __asm { + mov eax, 0x01080108 // generate multiplier to repeat 5 bits + vmovd xmm5, eax + vbroadcastss ymm5, xmm5 + mov eax, 0x20802080 // multiplier shift by 5 and then repeat 6 bits + vmovd xmm6, eax + vbroadcastss ymm6, xmm6 + vpcmpeqb ymm3, ymm3, ymm3 // generate mask 0xf800f800 for Red + vpsllw ymm3, ymm3, 11 + vpcmpeqb ymm4, ymm4, ymm4 // generate mask 0x07e007e0 for Green + vpsllw ymm4, ymm4, 10 + vpsrlw ymm4, ymm4, 5 + vpcmpeqb ymm7, ymm7, ymm7 // generate mask 0xff00ff00 for Alpha + vpsllw ymm7, ymm7, 8 + + mov eax, [esp + 4] // src_rgb565 + mov edx, [esp + 8] // dst_argb + mov ecx, [esp + 12] // width + sub edx, eax + sub edx, eax + + convertloop: + vmovdqu ymm0, [eax] // fetch 16 pixels of bgr565 + vpand ymm1, ymm0, ymm3 // R in upper 5 bits + vpsllw ymm2, ymm0, 11 // B in upper 5 bits + vpmulhuw ymm1, ymm1, ymm5 // * (256 + 8) + vpmulhuw ymm2, ymm2, ymm5 // * (256 + 8) + vpsllw ymm1, ymm1, 8 + vpor ymm1, ymm1, ymm2 // RB + vpand ymm0, ymm0, ymm4 // G in middle 6 bits + vpmulhuw ymm0, ymm0, ymm6 // << 5 * (256 + 4) + vpor ymm0, ymm0, ymm7 // AG + vpermq ymm0, ymm0, 0xd8 // mutate for unpack + vpermq ymm1, ymm1, 0xd8 + vpunpckhbw ymm2, ymm1, ymm0 + vpunpcklbw ymm1, ymm1, ymm0 + vmovdqu [eax * 2 + edx], ymm1 // store 4 pixels of ARGB + vmovdqu [eax * 2 + edx + 32], ymm2 // store next 4 pixels of ARGB + lea eax, [eax + 32] + sub ecx, 16 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_RGB565TOARGBROW_AVX2 + +#ifdef HAS_ARGB1555TOARGBROW_AVX2 +__declspec(naked) +void ARGB1555ToARGBRow_AVX2(const uint8* src_argb1555, uint8* dst_argb, + int width) { + __asm { + mov eax, 0x01080108 // generate multiplier to repeat 5 bits + vmovd xmm5, eax + vbroadcastss ymm5, xmm5 + mov eax, 0x42004200 // multiplier shift by 6 and then repeat 5 bits + vmovd xmm6, eax + vbroadcastss ymm6, xmm6 + vpcmpeqb ymm3, ymm3, ymm3 // generate mask 0xf800f800 for Red + vpsllw ymm3, ymm3, 11 + vpsrlw ymm4, ymm3, 6 // generate mask 0x03e003e0 for Green + vpcmpeqb ymm7, ymm7, ymm7 // generate mask 0xff00ff00 for Alpha + vpsllw ymm7, ymm7, 8 + + mov eax, [esp + 4] // src_argb1555 + mov edx, [esp + 8] // dst_argb + mov ecx, [esp + 12] // width + sub edx, eax + sub edx, eax + + convertloop: + vmovdqu ymm0, [eax] // fetch 16 pixels of 1555 + vpsllw ymm1, ymm0, 1 // R in upper 5 bits + vpsllw ymm2, ymm0, 11 // B in upper 5 bits + vpand ymm1, ymm1, ymm3 + vpmulhuw ymm2, ymm2, ymm5 // * (256 + 8) + vpmulhuw ymm1, ymm1, ymm5 // * (256 + 8) + vpsllw ymm1, ymm1, 8 + vpor ymm1, ymm1, ymm2 // RB + vpsraw ymm2, ymm0, 8 // A + vpand ymm0, ymm0, ymm4 // G in middle 5 bits + vpmulhuw ymm0, ymm0, ymm6 // << 6 * (256 + 8) + vpand ymm2, ymm2, ymm7 + vpor ymm0, ymm0, ymm2 // AG + vpermq ymm0, ymm0, 0xd8 // mutate for unpack + vpermq ymm1, ymm1, 0xd8 + vpunpckhbw ymm2, ymm1, ymm0 + vpunpcklbw ymm1, ymm1, ymm0 + vmovdqu [eax * 2 + edx], ymm1 // store 8 pixels of ARGB + vmovdqu [eax * 2 + edx + 32], ymm2 // store next 8 pixels of ARGB + lea eax, [eax + 32] + sub ecx, 16 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGB1555TOARGBROW_AVX2 + +#ifdef HAS_ARGB4444TOARGBROW_AVX2 +__declspec(naked) +void ARGB4444ToARGBRow_AVX2(const uint8* src_argb4444, uint8* dst_argb, + int width) { + __asm { + mov eax, 0x0f0f0f0f // generate mask 0x0f0f0f0f + vmovd xmm4, eax + vbroadcastss ymm4, xmm4 + vpslld ymm5, ymm4, 4 // 0xf0f0f0f0 for high nibbles + mov eax, [esp + 4] // src_argb4444 + mov edx, [esp + 8] // dst_argb + mov ecx, [esp + 12] // width + sub edx, eax + sub edx, eax + + convertloop: + vmovdqu ymm0, [eax] // fetch 16 pixels of bgra4444 + vpand ymm2, ymm0, ymm5 // mask high nibbles + vpand ymm0, ymm0, ymm4 // mask low nibbles + vpsrlw ymm3, ymm2, 4 + vpsllw ymm1, ymm0, 4 + vpor ymm2, ymm2, ymm3 + vpor ymm0, ymm0, ymm1 + vpermq ymm0, ymm0, 0xd8 // mutate for unpack + vpermq ymm2, ymm2, 0xd8 + vpunpckhbw ymm1, ymm0, ymm2 + vpunpcklbw ymm0, ymm0, ymm2 + vmovdqu [eax * 2 + edx], ymm0 // store 8 pixels of ARGB + vmovdqu [eax * 2 + edx + 32], ymm1 // store next 8 pixels of ARGB + lea eax, [eax + 32] + sub ecx, 16 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGB4444TOARGBROW_AVX2 + // 24 instructions -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGB1555ToARGBRow_SSE2(const uint8* src_argb1555, uint8* dst_argb, - int pix) { + int width) { __asm { mov eax, 0x01080108 // generate multiplier to repeat 5 bits movd xmm5, eax @@ -519,11 +677,10 @@ void ARGB1555ToARGBRow_SSE2(const uint8* src_argb1555, uint8* dst_argb, mov eax, [esp + 4] // src_argb1555 mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width sub edx, eax sub edx, eax - align 4 convertloop: movdqu xmm0, [eax] // fetch 8 pixels of 1555 movdqa xmm1, xmm0 @@ -544,8 +701,8 @@ void ARGB1555ToARGBRow_SSE2(const uint8* src_argb1555, uint8* dst_argb, movdqa xmm2, xmm1 punpcklbw xmm1, xmm0 punpckhbw xmm2, xmm0 - movdqa [eax * 2 + edx], xmm1 // store 4 pixels of ARGB - movdqa [eax * 2 + edx + 16], xmm2 // store next 4 pixels of ARGB + movdqu [eax * 2 + edx], xmm1 // store 4 pixels of ARGB + movdqu [eax * 2 + edx + 16], xmm2 // store next 4 pixels of ARGB lea eax, [eax + 16] sub ecx, 8 jg convertloop @@ -554,9 +711,9 @@ void ARGB1555ToARGBRow_SSE2(const uint8* src_argb1555, uint8* dst_argb, } // 18 instructions. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGB4444ToARGBRow_SSE2(const uint8* src_argb4444, uint8* dst_argb, - int pix) { + int width) { __asm { mov eax, 0x0f0f0f0f // generate mask 0x0f0f0f0f movd xmm4, eax @@ -565,11 +722,10 @@ void ARGB4444ToARGBRow_SSE2(const uint8* src_argb4444, uint8* dst_argb, pslld xmm5, 4 mov eax, [esp + 4] // src_argb4444 mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width sub edx, eax sub edx, eax - align 4 convertloop: movdqu xmm0, [eax] // fetch 8 pixels of bgra4444 movdqa xmm2, xmm0 @@ -584,8 +740,8 @@ void ARGB4444ToARGBRow_SSE2(const uint8* src_argb4444, uint8* dst_argb, movdqa xmm1, xmm0 punpcklbw xmm0, xmm2 punpckhbw xmm1, xmm2 - movdqa [eax * 2 + edx], xmm0 // store 4 pixels of ARGB - movdqa [eax * 2 + edx + 16], xmm1 // store next 4 pixels of ARGB + movdqu [eax * 2 + edx], xmm0 // store 4 pixels of ARGB + movdqu [eax * 2 + edx + 16], xmm1 // store next 4 pixels of ARGB lea eax, [eax + 16] sub ecx, 8 jg convertloop @@ -593,15 +749,14 @@ void ARGB4444ToARGBRow_SSE2(const uint8* src_argb4444, uint8* dst_argb, } } -__declspec(naked) __declspec(align(16)) -void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix) { +__declspec(naked) +void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_rgb - mov ecx, [esp + 12] // pix - movdqa xmm6, kShuffleMaskARGBToRGB24 + mov ecx, [esp + 12] // width + movdqa xmm6, xmmword ptr kShuffleMaskARGBToRGB24 - align 4 convertloop: movdqu xmm0, [eax] // fetch 16 pixels of argb movdqu xmm1, [eax + 16] @@ -632,15 +787,14 @@ void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix) { } } -__declspec(naked) __declspec(align(16)) -void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix) { +__declspec(naked) +void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_rgb - mov ecx, [esp + 12] // pix - movdqa xmm6, kShuffleMaskARGBToRAW + mov ecx, [esp + 12] // width + movdqa xmm6, xmmword ptr kShuffleMaskARGBToRAW - align 4 convertloop: movdqu xmm0, [eax] // fetch 16 pixels of argb movdqu xmm1, [eax + 16] @@ -671,12 +825,12 @@ void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int pix) { } } -__declspec(naked) __declspec(align(16)) -void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { +__declspec(naked) +void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_rgb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm3, xmm3 // generate mask 0x0000001f psrld xmm3, 27 pcmpeqb xmm4, xmm4 // generate mask 0x000007e0 @@ -685,9 +839,8 @@ void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { pcmpeqb xmm5, xmm5 // generate mask 0xfffff800 pslld xmm5, 11 - align 4 convertloop: - movdqa xmm0, [eax] // fetch 4 pixels of argb + movdqu xmm0, [eax] // fetch 4 pixels of argb movdqa xmm1, xmm0 // B movdqa xmm2, xmm0 // G pslld xmm0, 8 // R @@ -709,13 +862,101 @@ void ARGBToRGB565Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { } } +__declspec(naked) +void ARGBToRGB565DitherRow_SSE2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) { + __asm { + + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgb + movd xmm6, [esp + 12] // dither4 + mov ecx, [esp + 16] // width + punpcklbw xmm6, xmm6 // make dither 16 bytes + movdqa xmm7, xmm6 + punpcklwd xmm6, xmm6 + punpckhwd xmm7, xmm7 + pcmpeqb xmm3, xmm3 // generate mask 0x0000001f + psrld xmm3, 27 + pcmpeqb xmm4, xmm4 // generate mask 0x000007e0 + psrld xmm4, 26 + pslld xmm4, 5 + pcmpeqb xmm5, xmm5 // generate mask 0xfffff800 + pslld xmm5, 11 + + convertloop: + movdqu xmm0, [eax] // fetch 4 pixels of argb + paddusb xmm0, xmm6 // add dither + movdqa xmm1, xmm0 // B + movdqa xmm2, xmm0 // G + pslld xmm0, 8 // R + psrld xmm1, 3 // B + psrld xmm2, 5 // G + psrad xmm0, 16 // R + pand xmm1, xmm3 // B + pand xmm2, xmm4 // G + pand xmm0, xmm5 // R + por xmm1, xmm2 // BG + por xmm0, xmm1 // BGR + packssdw xmm0, xmm0 + lea eax, [eax + 16] + movq qword ptr [edx], xmm0 // store 4 pixels of RGB565 + lea edx, [edx + 8] + sub ecx, 4 + jg convertloop + ret + } +} + +#ifdef HAS_ARGBTORGB565DITHERROW_AVX2 +__declspec(naked) +void ARGBToRGB565DitherRow_AVX2(const uint8* src_argb, uint8* dst_rgb, + const uint32 dither4, int width) { + __asm { + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgb + vbroadcastss xmm6, [esp + 12] // dither4 + mov ecx, [esp + 16] // width + vpunpcklbw xmm6, xmm6, xmm6 // make dither 32 bytes + vpermq ymm6, ymm6, 0xd8 + vpunpcklwd ymm6, ymm6, ymm6 + vpcmpeqb ymm3, ymm3, ymm3 // generate mask 0x0000001f + vpsrld ymm3, ymm3, 27 + vpcmpeqb ymm4, ymm4, ymm4 // generate mask 0x000007e0 + vpsrld ymm4, ymm4, 26 + vpslld ymm4, ymm4, 5 + vpslld ymm5, ymm3, 11 // generate mask 0x0000f800 + + convertloop: + vmovdqu ymm0, [eax] // fetch 8 pixels of argb + vpaddusb ymm0, ymm0, ymm6 // add dither + vpsrld ymm2, ymm0, 5 // G + vpsrld ymm1, ymm0, 3 // B + vpsrld ymm0, ymm0, 8 // R + vpand ymm2, ymm2, ymm4 // G + vpand ymm1, ymm1, ymm3 // B + vpand ymm0, ymm0, ymm5 // R + vpor ymm1, ymm1, ymm2 // BG + vpor ymm0, ymm0, ymm1 // BGR + vpackusdw ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 + lea eax, [eax + 32] + vmovdqu [edx], xmm0 // store 8 pixels of RGB565 + lea edx, [edx + 16] + sub ecx, 8 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGBTORGB565DITHERROW_AVX2 + // TODO(fbarchard): Improve sign extension/packing. -__declspec(naked) __declspec(align(16)) -void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { +__declspec(naked) +void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_rgb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm4, xmm4 // generate mask 0x0000001f psrld xmm4, 27 movdqa xmm5, xmm4 // generate mask 0x000003e0 @@ -725,9 +966,8 @@ void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { pcmpeqb xmm7, xmm7 // generate mask 0xffff8000 pslld xmm7, 15 - align 4 convertloop: - movdqa xmm0, [eax] // fetch 4 pixels of argb + movdqu xmm0, [eax] // fetch 4 pixels of argb movdqa xmm1, xmm0 // B movdqa xmm2, xmm0 // G movdqa xmm3, xmm0 // R @@ -752,25 +992,24 @@ void ARGBToARGB1555Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { } } -__declspec(naked) __declspec(align(16)) -void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { +__declspec(naked) +void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_rgb - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm4, xmm4 // generate mask 0xf000f000 psllw xmm4, 12 movdqa xmm3, xmm4 // generate mask 0x00f000f0 psrlw xmm3, 8 - align 4 convertloop: - movdqa xmm0, [eax] // fetch 4 pixels of argb + movdqu xmm0, [eax] // fetch 4 pixels of argb movdqa xmm1, xmm0 pand xmm0, xmm3 // low nibble pand xmm1, xmm4 // high nibble - psrl xmm0, 4 - psrl xmm1, 8 + psrld xmm0, 4 + psrld xmm1, 8 por xmm0, xmm1 packuswb xmm0, xmm0 lea eax, [eax + 16] @@ -782,22 +1021,129 @@ void ARGBToARGB4444Row_SSE2(const uint8* src_argb, uint8* dst_rgb, int pix) { } } +#ifdef HAS_ARGBTORGB565ROW_AVX2 +__declspec(naked) +void ARGBToRGB565Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width) { + __asm { + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgb + mov ecx, [esp + 12] // width + vpcmpeqb ymm3, ymm3, ymm3 // generate mask 0x0000001f + vpsrld ymm3, ymm3, 27 + vpcmpeqb ymm4, ymm4, ymm4 // generate mask 0x000007e0 + vpsrld ymm4, ymm4, 26 + vpslld ymm4, ymm4, 5 + vpslld ymm5, ymm3, 11 // generate mask 0x0000f800 + + convertloop: + vmovdqu ymm0, [eax] // fetch 8 pixels of argb + vpsrld ymm2, ymm0, 5 // G + vpsrld ymm1, ymm0, 3 // B + vpsrld ymm0, ymm0, 8 // R + vpand ymm2, ymm2, ymm4 // G + vpand ymm1, ymm1, ymm3 // B + vpand ymm0, ymm0, ymm5 // R + vpor ymm1, ymm1, ymm2 // BG + vpor ymm0, ymm0, ymm1 // BGR + vpackusdw ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 + lea eax, [eax + 32] + vmovdqu [edx], xmm0 // store 8 pixels of RGB565 + lea edx, [edx + 16] + sub ecx, 8 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGBTORGB565ROW_AVX2 + +#ifdef HAS_ARGBTOARGB1555ROW_AVX2 +__declspec(naked) +void ARGBToARGB1555Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width) { + __asm { + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgb + mov ecx, [esp + 12] // width + vpcmpeqb ymm4, ymm4, ymm4 + vpsrld ymm4, ymm4, 27 // generate mask 0x0000001f + vpslld ymm5, ymm4, 5 // generate mask 0x000003e0 + vpslld ymm6, ymm4, 10 // generate mask 0x00007c00 + vpcmpeqb ymm7, ymm7, ymm7 // generate mask 0xffff8000 + vpslld ymm7, ymm7, 15 + + convertloop: + vmovdqu ymm0, [eax] // fetch 8 pixels of argb + vpsrld ymm3, ymm0, 9 // R + vpsrld ymm2, ymm0, 6 // G + vpsrld ymm1, ymm0, 3 // B + vpsrad ymm0, ymm0, 16 // A + vpand ymm3, ymm3, ymm6 // R + vpand ymm2, ymm2, ymm5 // G + vpand ymm1, ymm1, ymm4 // B + vpand ymm0, ymm0, ymm7 // A + vpor ymm0, ymm0, ymm1 // BA + vpor ymm2, ymm2, ymm3 // GR + vpor ymm0, ymm0, ymm2 // BGRA + vpackssdw ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 + lea eax, [eax + 32] + vmovdqu [edx], xmm0 // store 8 pixels of ARGB1555 + lea edx, [edx + 16] + sub ecx, 8 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGBTOARGB1555ROW_AVX2 + +#ifdef HAS_ARGBTOARGB4444ROW_AVX2 +__declspec(naked) +void ARGBToARGB4444Row_AVX2(const uint8* src_argb, uint8* dst_rgb, int width) { + __asm { + mov eax, [esp + 4] // src_argb + mov edx, [esp + 8] // dst_rgb + mov ecx, [esp + 12] // width + vpcmpeqb ymm4, ymm4, ymm4 // generate mask 0xf000f000 + vpsllw ymm4, ymm4, 12 + vpsrlw ymm3, ymm4, 8 // generate mask 0x00f000f0 + + convertloop: + vmovdqu ymm0, [eax] // fetch 8 pixels of argb + vpand ymm1, ymm0, ymm4 // high nibble + vpand ymm0, ymm0, ymm3 // low nibble + vpsrld ymm1, ymm1, 8 + vpsrld ymm0, ymm0, 4 + vpor ymm0, ymm0, ymm1 + vpackuswb ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 + lea eax, [eax + 32] + vmovdqu [edx], xmm0 // store 8 pixels of ARGB4444 + lea edx, [edx + 16] + sub ecx, 8 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_ARGBTOARGB4444ROW_AVX2 + // Convert 16 ARGB pixels (64 bytes) to 16 Y values. -__declspec(naked) __declspec(align(16)) -void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kARGBToY + mov ecx, [esp + 12] /* width */ + movdqa xmm4, xmmword ptr kARGBToY + movdqa xmm5, xmmword ptr kAddY16 - align 4 convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + 32] + movdqu xmm3, [eax + 48] pmaddubsw xmm0, xmm4 pmaddubsw xmm1, xmm4 pmaddubsw xmm2, xmm4 @@ -809,30 +1155,30 @@ void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { psrlw xmm2, 7 packuswb xmm0, xmm2 paddb xmm0, xmm5 - sub ecx, 16 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop ret } } -// Convert 16 ARGB pixels (64 bytes) to 16 Y values. -__declspec(naked) __declspec(align(16)) -void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { +// Convert 16 ARGB pixels (64 bytes) to 16 YJ values. +// Same as ARGBToYRow but different coefficients, no add 16, but do rounding. +__declspec(naked) +void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm4, kARGBToYJ - movdqa xmm5, kAddYJ64 + mov ecx, [esp + 12] /* width */ + movdqa xmm4, xmmword ptr kARGBToYJ + movdqa xmm5, xmmword ptr kAddYJ64 - align 4 convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + 32] + movdqu xmm3, [eax + 48] pmaddubsw xmm0, xmm4 pmaddubsw xmm1, xmm4 pmaddubsw xmm2, xmm4 @@ -845,27 +1191,31 @@ void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { psrlw xmm0, 7 psrlw xmm2, 7 packuswb xmm0, xmm2 - sub ecx, 16 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop ret } } #ifdef HAS_ARGBTOYROW_AVX2 +// vpermd for vphaddw + vpackuswb vpermd. +static const lvec32 kPermdARGBToY_AVX = { + 0, 4, 1, 5, 2, 6, 3, 7 +}; + // Convert 32 ARGB pixels (128 bytes) to 32 Y values. -__declspec(naked) __declspec(align(32)) -void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - vbroadcastf128 ymm4, kARGBToY - vbroadcastf128 ymm5, kAddY16 - vmovdqa ymm6, kPermdARGBToY_AVX + mov ecx, [esp + 12] /* width */ + vbroadcastf128 ymm4, xmmword ptr kARGBToY + vbroadcastf128 ymm5, xmmword ptr kAddY16 + vmovdqu ymm6, ymmword ptr kPermdARGBToY_AVX - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -882,10 +1232,10 @@ void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { vpsrlw ymm2, ymm2, 7 vpackuswb ymm0, ymm0, ymm2 // mutates. vpermd ymm0, ymm6, ymm0 // For vphaddw + vpackuswb mutation. - vpaddb ymm0, ymm0, ymm5 - sub ecx, 32 + vpaddb ymm0, ymm0, ymm5 // add 16 for Y vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 32 jg convertloop vzeroupper ret @@ -893,19 +1243,18 @@ void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { } #endif // HAS_ARGBTOYROW_AVX2 -#ifdef HAS_ARGBTOYROW_AVX2 +#ifdef HAS_ARGBTOYJROW_AVX2 // Convert 32 ARGB pixels (128 bytes) to 32 Y values. -__declspec(naked) __declspec(align(32)) -void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - vbroadcastf128 ymm4, kARGBToYJ - vbroadcastf128 ymm5, kAddYJ64 - vmovdqa ymm6, kPermdARGBToY_AVX + mov ecx, [esp + 12] /* width */ + vbroadcastf128 ymm4, xmmword ptr kARGBToYJ + vbroadcastf128 ymm5, xmmword ptr kAddYJ64 + vmovdqu ymm6, ymmword ptr kPermdARGBToY_AVX - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -924,9 +1273,9 @@ void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { vpsrlw ymm2, ymm2, 7 vpackuswb ymm0, ymm0, ymm2 // mutates. vpermd ymm0, ymm6, ymm0 // For vphaddw + vpackuswb mutation. - sub ecx, 32 vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 32 jg convertloop vzeroupper @@ -935,16 +1284,15 @@ void ARGBToYJRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix) { } #endif // HAS_ARGBTOYJROW_AVX2 -__declspec(naked) __declspec(align(16)) -void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void BGRAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kARGBToY + mov ecx, [esp + 12] /* width */ + movdqa xmm4, xmmword ptr kBGRAToY + movdqa xmm5, xmmword ptr kAddY16 - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -961,93 +1309,23 @@ void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { psrlw xmm2, 7 packuswb xmm0, xmm2 paddb xmm0, xmm5 - sub ecx, 16 movdqu [edx], xmm0 lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] /* src_argb */ - mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm4, kARGBToYJ - movdqa xmm5, kAddYJ64 - - align 4 - convertloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] - pmaddubsw xmm0, xmm4 - pmaddubsw xmm1, xmm4 - pmaddubsw xmm2, xmm4 - pmaddubsw xmm3, xmm4 - lea eax, [eax + 64] - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - paddw xmm0, xmm5 - paddw xmm2, xmm5 - psrlw xmm0, 7 - psrlw xmm2, 7 - packuswb xmm0, xmm2 sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] jg convertloop ret } } -__declspec(naked) __declspec(align(16)) -void BGRAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void ABGRToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kBGRAToY + mov ecx, [esp + 12] /* width */ + movdqa xmm4, xmmword ptr kABGRToY + movdqa xmm5, xmmword ptr kAddY16 - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pmaddubsw xmm0, xmm4 - pmaddubsw xmm1, xmm4 - pmaddubsw xmm2, xmm4 - pmaddubsw xmm3, xmm4 - lea eax, [eax + 64] - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psrlw xmm0, 7 - psrlw xmm2, 7 - packuswb xmm0, xmm2 - paddb xmm0, xmm5 - sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void BGRAToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] /* src_argb */ - mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kBGRAToY - - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -1064,58 +1342,23 @@ void BGRAToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { psrlw xmm2, 7 packuswb xmm0, xmm2 paddb xmm0, xmm5 - sub ecx, 16 movdqu [edx], xmm0 lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ABGRToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] /* src_argb */ - mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kABGRToY - - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pmaddubsw xmm0, xmm4 - pmaddubsw xmm1, xmm4 - pmaddubsw xmm2, xmm4 - pmaddubsw xmm3, xmm4 - lea eax, [eax + 64] - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psrlw xmm0, 7 - psrlw xmm2, 7 - packuswb xmm0, xmm2 - paddb xmm0, xmm5 sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] jg convertloop ret } } -__declspec(naked) __declspec(align(16)) -void ABGRToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { +__declspec(naked) +void RGBAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kABGRToY + mov ecx, [esp + 12] /* width */ + movdqa xmm4, xmmword ptr kRGBAToY + movdqa xmm5, xmmword ptr kAddY16 - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -1132,83 +1375,15 @@ void ABGRToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { psrlw xmm2, 7 packuswb xmm0, xmm2 paddb xmm0, xmm5 - sub ecx, 16 movdqu [edx], xmm0 lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void RGBAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] /* src_argb */ - mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kRGBAToY - - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pmaddubsw xmm0, xmm4 - pmaddubsw xmm1, xmm4 - pmaddubsw xmm2, xmm4 - pmaddubsw xmm3, xmm4 - lea eax, [eax + 64] - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psrlw xmm0, 7 - psrlw xmm2, 7 - packuswb xmm0, xmm2 - paddb xmm0, xmm5 sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] jg convertloop ret } } -__declspec(naked) __declspec(align(16)) -void RGBAToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] /* src_argb */ - mov edx, [esp + 8] /* dst_y */ - mov ecx, [esp + 12] /* pix */ - movdqa xmm5, kAddY16 - movdqa xmm4, kRGBAToY - - align 4 - convertloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] - pmaddubsw xmm0, xmm4 - pmaddubsw xmm1, xmm4 - pmaddubsw xmm2, xmm4 - pmaddubsw xmm3, xmm4 - lea eax, [eax + 64] - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psrlw xmm0, 7 - psrlw xmm2, 7 - packuswb xmm0, xmm2 - paddb xmm0, xmm5 - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1218,23 +1393,27 @@ void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 8 + 20] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kARGBToV + movdqa xmm7, xmmword ptr kARGBToU sub edi, edx // stride from u to v - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pavgb xmm0, [eax + esi] - pavgb xmm1, [eax + esi + 16] - pavgb xmm2, [eax + esi + 32] - pavgb xmm3, [eax + esi + 48] + movdqu xmm0, [eax] + movdqu xmm4, [eax + esi] + pavgb xmm0, xmm4 + movdqu xmm1, [eax + 16] + movdqu xmm4, [eax + esi + 16] + pavgb xmm1, xmm4 + movdqu xmm2, [eax + 32] + movdqu xmm4, [eax + esi + 32] + pavgb xmm2, xmm4 + movdqu xmm3, [eax + 48] + movdqu xmm4, [eax + esi + 48] + pavgb xmm3, xmm4 + lea eax, [eax + 64] movdqa xmm4, xmm0 shufps xmm0, xmm1, 0x88 @@ -1262,10 +1441,10 @@ void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, paddb xmm0, xmm5 // -> unsigned // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -1274,7 +1453,7 @@ void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBToUVJRow_SSSE3(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1284,23 +1463,27 @@ void ARGBToUVJRow_SSSE3(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kARGBToUJ - movdqa xmm6, kARGBToVJ - movdqa xmm5, kAddUVJ128 + mov ecx, [esp + 8 + 20] // width + movdqa xmm5, xmmword ptr kAddUVJ128 + movdqa xmm6, xmmword ptr kARGBToVJ + movdqa xmm7, xmmword ptr kARGBToUJ sub edi, edx // stride from u to v - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pavgb xmm0, [eax + esi] - pavgb xmm1, [eax + esi + 16] - pavgb xmm2, [eax + esi + 32] - pavgb xmm3, [eax + esi + 48] + movdqu xmm0, [eax] + movdqu xmm4, [eax + esi] + pavgb xmm0, xmm4 + movdqu xmm1, [eax + 16] + movdqu xmm4, [eax + esi + 16] + pavgb xmm1, xmm4 + movdqu xmm2, [eax + 32] + movdqu xmm4, [eax + esi + 32] + pavgb xmm2, xmm4 + movdqu xmm3, [eax + 48] + movdqu xmm4, [eax + esi + 48] + pavgb xmm3, xmm4 + lea eax, [eax + 64] movdqa xmm4, xmm0 shufps xmm0, xmm1, 0x88 @@ -1329,10 +1512,10 @@ void ARGBToUVJRow_SSSE3(const uint8* src_argb0, int src_stride_argb, packsswb xmm0, xmm1 // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -1342,7 +1525,7 @@ void ARGBToUVJRow_SSSE3(const uint8* src_argb0, int src_stride_argb, } #ifdef HAS_ARGBTOUVROW_AVX2 -__declspec(naked) __declspec(align(32)) +__declspec(naked) void ARGBToUVRow_AVX2(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1352,13 +1535,12 @@ void ARGBToUVRow_AVX2(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - vbroadcastf128 ymm5, kAddUV128 - vbroadcastf128 ymm6, kARGBToV - vbroadcastf128 ymm7, kARGBToU + mov ecx, [esp + 8 + 20] // width + vbroadcastf128 ymm5, xmmword ptr kAddUV128 + vbroadcastf128 ymm6, xmmword ptr kARGBToV + vbroadcastf128 ymm7, xmmword ptr kARGBToU sub edi, edx // stride from u to v - align 4 convertloop: /* step 1 - subsample 32x2 argb pixels to 16x1 */ vmovdqu ymm0, [eax] @@ -1390,14 +1572,14 @@ void ARGBToUVRow_AVX2(const uint8* src_argb0, int src_stride_argb, vpsraw ymm0, ymm0, 8 vpacksswb ymm0, ymm1, ymm0 // mutates vpermq ymm0, ymm0, 0xd8 // For vpacksswb - vpshufb ymm0, ymm0, kShufARGBToUV_AVX // For vshufps + vphaddw + vpshufb ymm0, ymm0, ymmword ptr kShufARGBToUV_AVX // for vshufps/vphaddw vpaddb ymm0, ymm0, ymm5 // -> unsigned // step 3 - store 16 U and 16 V values - sub ecx, 32 vextractf128 [edx], ymm0, 0 // U vextractf128 [edx + edi], ymm0, 1 // V lea edx, [edx + 16] + sub ecx, 32 jg convertloop pop edi @@ -1408,148 +1590,7 @@ void ARGBToUVRow_AVX2(const uint8* src_argb0, int src_stride_argb, } #endif // HAS_ARGBTOUVROW_AVX2 -__declspec(naked) __declspec(align(16)) -void ARGBToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_argb - mov esi, [esp + 8 + 8] // src_stride_argb - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] - movdqu xmm4, [eax + esi] - pavgb xmm0, xmm4 - movdqu xmm4, [eax + esi + 16] - pavgb xmm1, xmm4 - movdqu xmm4, [eax + esi + 32] - pavgb xmm2, xmm4 - movdqu xmm4, [eax + esi + 48] - pavgb xmm3, xmm4 - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - paddb xmm0, xmm5 // -> unsigned - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ARGBToUVJRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_argb - mov esi, [esp + 8 + 8] // src_stride_argb - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kARGBToUJ - movdqa xmm6, kARGBToVJ - movdqa xmm5, kAddUVJ128 - sub edi, edx // stride from u to v - - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] - movdqu xmm4, [eax + esi] - pavgb xmm0, xmm4 - movdqu xmm4, [eax + esi + 16] - pavgb xmm1, xmm4 - movdqu xmm4, [eax + esi + 32] - pavgb xmm2, xmm4 - movdqu xmm4, [eax + esi + 48] - pavgb xmm3, xmm4 - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - paddw xmm0, xmm5 // +.5 rounding -> unsigned - paddw xmm1, xmm5 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBToUV444Row_SSSE3(const uint8* src_argb0, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1557,71 +1598,12 @@ void ARGBToUV444Row_SSSE3(const uint8* src_argb0, mov eax, [esp + 4 + 4] // src_argb mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 4 + 16] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kARGBToV + movdqa xmm7, xmmword ptr kARGBToU sub edi, edx // stride from u to v - align 4 - convertloop: - /* convert to U and V */ - movdqa xmm0, [eax] // U - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pmaddubsw xmm0, xmm7 - pmaddubsw xmm1, xmm7 - pmaddubsw xmm2, xmm7 - pmaddubsw xmm3, xmm7 - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psraw xmm0, 8 - psraw xmm2, 8 - packsswb xmm0, xmm2 - paddb xmm0, xmm5 - sub ecx, 16 - movdqa [edx], xmm0 - - movdqa xmm0, [eax] // V - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pmaddubsw xmm0, xmm6 - pmaddubsw xmm1, xmm6 - pmaddubsw xmm2, xmm6 - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm1 - phaddw xmm2, xmm3 - psraw xmm0, 8 - psraw xmm2, 8 - packsswb xmm0, xmm2 - paddb xmm0, xmm5 - lea eax, [eax + 64] - movdqa [edx + edi], xmm0 - lea edx, [edx + 16] - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb0, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_argb - mov edx, [esp + 4 + 8] // dst_u - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 convertloop: /* convert to U and V */ movdqu xmm0, [eax] // U @@ -1638,7 +1620,6 @@ void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb0, psraw xmm2, 8 packsswb xmm0, xmm2 paddb xmm0, xmm5 - sub ecx, 16 movdqu [edx], xmm0 movdqu xmm0, [eax] // V @@ -1658,6 +1639,7 @@ void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb0, lea eax, [eax + 64] movdqu [edx + edi], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop pop edi @@ -1665,7 +1647,7 @@ void ARGBToUV444Row_Unaligned_SSSE3(const uint8* src_argb0, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBToUV422Row_SSSE3(const uint8* src_argb0, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1673,72 +1655,12 @@ void ARGBToUV422Row_SSSE3(const uint8* src_argb0, mov eax, [esp + 4 + 4] // src_argb mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 4 + 16] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kARGBToV + movdqa xmm7, xmmword ptr kARGBToU sub edi, edx // stride from u to v - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - paddb xmm0, xmm5 // -> unsigned - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ARGBToUV422Row_Unaligned_SSSE3(const uint8* src_argb0, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_argb - mov edx, [esp + 4 + 8] // dst_u - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - movdqa xmm7, kARGBToU - movdqa xmm6, kARGBToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ movdqu xmm0, [eax] @@ -1772,10 +1694,10 @@ void ARGBToUV422Row_Unaligned_SSSE3(const uint8* src_argb0, paddb xmm0, xmm5 // -> unsigned // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -1783,7 +1705,7 @@ void ARGBToUV422Row_Unaligned_SSSE3(const uint8* src_argb0, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void BGRAToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1793,93 +1715,27 @@ void BGRAToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kBGRAToU - movdqa xmm6, kBGRAToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 8 + 20] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kBGRAToV + movdqa xmm7, xmmword ptr kBGRAToU sub edi, edx // stride from u to v - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pavgb xmm0, [eax + esi] - pavgb xmm1, [eax + esi + 16] - pavgb xmm2, [eax + esi + 32] - pavgb xmm3, [eax + esi + 48] - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - paddb xmm0, xmm5 // -> unsigned - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void BGRAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_argb - mov esi, [esp + 8 + 8] // src_stride_argb - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kBGRAToU - movdqa xmm6, kBGRAToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi] pavgb xmm0, xmm4 + movdqu xmm1, [eax + 16] movdqu xmm4, [eax + esi + 16] pavgb xmm1, xmm4 + movdqu xmm2, [eax + 32] movdqu xmm4, [eax + esi + 32] pavgb xmm2, xmm4 + movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi + 48] pavgb xmm3, xmm4 + lea eax, [eax + 64] movdqa xmm4, xmm0 shufps xmm0, xmm1, 0x88 @@ -1907,10 +1763,10 @@ void BGRAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, paddb xmm0, xmm5 // -> unsigned // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -1919,7 +1775,7 @@ void BGRAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ABGRToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -1929,93 +1785,27 @@ void ABGRToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kABGRToU - movdqa xmm6, kABGRToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 8 + 20] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kABGRToV + movdqa xmm7, xmmword ptr kABGRToU sub edi, edx // stride from u to v - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pavgb xmm0, [eax + esi] - pavgb xmm1, [eax + esi + 16] - pavgb xmm2, [eax + esi + 32] - pavgb xmm3, [eax + esi + 48] - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - paddb xmm0, xmm5 // -> unsigned - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ABGRToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_argb - mov esi, [esp + 8 + 8] // src_stride_argb - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kABGRToU - movdqa xmm6, kABGRToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi] pavgb xmm0, xmm4 + movdqu xmm1, [eax + 16] movdqu xmm4, [eax + esi + 16] pavgb xmm1, xmm4 + movdqu xmm2, [eax + 32] movdqu xmm4, [eax + esi + 32] pavgb xmm2, xmm4 + movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi + 48] pavgb xmm3, xmm4 + lea eax, [eax + 64] movdqa xmm4, xmm0 shufps xmm0, xmm1, 0x88 @@ -2043,10 +1833,10 @@ void ABGRToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, paddb xmm0, xmm5 // -> unsigned // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -2055,7 +1845,7 @@ void ABGRToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void RGBAToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -2065,93 +1855,27 @@ void RGBAToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb, mov esi, [esp + 8 + 8] // src_stride_argb mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kRGBAToU - movdqa xmm6, kRGBAToV - movdqa xmm5, kAddUV128 + mov ecx, [esp + 8 + 20] // width + movdqa xmm5, xmmword ptr kAddUV128 + movdqa xmm6, xmmword ptr kRGBAToV + movdqa xmm7, xmmword ptr kRGBAToU sub edi, edx // stride from u to v - align 4 - convertloop: - /* step 1 - subsample 16x2 argb pixels to 8x1 */ - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] - pavgb xmm0, [eax + esi] - pavgb xmm1, [eax + esi + 16] - pavgb xmm2, [eax + esi + 32] - pavgb xmm3, [eax + esi + 48] - lea eax, [eax + 64] - movdqa xmm4, xmm0 - shufps xmm0, xmm1, 0x88 - shufps xmm4, xmm1, 0xdd - pavgb xmm0, xmm4 - movdqa xmm4, xmm2 - shufps xmm2, xmm3, 0x88 - shufps xmm4, xmm3, 0xdd - pavgb xmm2, xmm4 - - // step 2 - convert to U and V - // from here down is very similar to Y code except - // instead of 16 different pixels, its 8 pixels of U and 8 of V - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - pmaddubsw xmm0, xmm7 // U - pmaddubsw xmm2, xmm7 - pmaddubsw xmm1, xmm6 // V - pmaddubsw xmm3, xmm6 - phaddw xmm0, xmm2 - phaddw xmm1, xmm3 - psraw xmm0, 8 - psraw xmm1, 8 - packsswb xmm0, xmm1 - paddb xmm0, xmm5 // -> unsigned - - // step 3 - store 8 U and 8 V values - sub ecx, 16 - movlps qword ptr [edx], xmm0 // U - movhps qword ptr [edx + edi], xmm0 // V - lea edx, [edx + 8] - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void RGBAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, - uint8* dst_u, uint8* dst_v, int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_argb - mov esi, [esp + 8 + 8] // src_stride_argb - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - movdqa xmm7, kRGBAToU - movdqa xmm6, kRGBAToV - movdqa xmm5, kAddUV128 - sub edi, edx // stride from u to v - - align 4 convertloop: /* step 1 - subsample 16x2 argb pixels to 8x1 */ movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + 32] - movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi] pavgb xmm0, xmm4 + movdqu xmm1, [eax + 16] movdqu xmm4, [eax + esi + 16] pavgb xmm1, xmm4 + movdqu xmm2, [eax + 32] movdqu xmm4, [eax + esi + 32] pavgb xmm2, xmm4 + movdqu xmm3, [eax + 48] movdqu xmm4, [eax + esi + 48] pavgb xmm3, xmm4 + lea eax, [eax + 64] movdqa xmm4, xmm0 shufps xmm0, xmm1, 0x88 @@ -2179,10 +1903,10 @@ void RGBAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, paddb xmm0, xmm5 // -> unsigned // step 3 - store 8 U and 8 V values - sub ecx, 16 movlps qword ptr [edx], xmm0 // U movhps qword ptr [edx + edi], xmm0 // V lea edx, [edx + 8] + sub ecx, 16 jg convertloop pop edi @@ -2192,119 +1916,505 @@ void RGBAToUVRow_Unaligned_SSSE3(const uint8* src_argb0, int src_stride_argb, } #endif // HAS_ARGBTOYROW_SSSE3 +// Read 16 UV from 444 +#define READYUV444_AVX2 __asm { \ + __asm vmovdqu xmm0, [esi] /* U */ \ + __asm vmovdqu xmm1, [esi + edi] /* V */ \ + __asm lea esi, [esi + 16] \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpermq ymm1, ymm1, 0xd8 \ + __asm vpunpcklbw ymm0, ymm0, ymm1 /* UV */ \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + } + +// Read 8 UV from 422, upsample to 16 UV. +#define READYUV422_AVX2 __asm { \ + __asm vmovq xmm0, qword ptr [esi] /* U */ \ + __asm vmovq xmm1, qword ptr [esi + edi] /* V */ \ + __asm lea esi, [esi + 8] \ + __asm vpunpcklbw ymm0, ymm0, ymm1 /* UV */ \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpunpcklwd ymm0, ymm0, ymm0 /* UVUV (upsample) */ \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + } + +// Read 8 UV from 422, upsample to 16 UV. With 16 Alpha. +#define READYUVA422_AVX2 __asm { \ + __asm vmovq xmm0, qword ptr [esi] /* U */ \ + __asm vmovq xmm1, qword ptr [esi + edi] /* V */ \ + __asm lea esi, [esi + 8] \ + __asm vpunpcklbw ymm0, ymm0, ymm1 /* UV */ \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpunpcklwd ymm0, ymm0, ymm0 /* UVUV (upsample) */ \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + __asm vmovdqu xmm5, [ebp] /* A */ \ + __asm vpermq ymm5, ymm5, 0xd8 \ + __asm lea ebp, [ebp + 16] \ + } + +// Read 4 UV from 411, upsample to 16 UV. +#define READYUV411_AVX2 __asm { \ + __asm vmovd xmm0, dword ptr [esi] /* U */ \ + __asm vmovd xmm1, dword ptr [esi + edi] /* V */ \ + __asm lea esi, [esi + 4] \ + __asm vpunpcklbw ymm0, ymm0, ymm1 /* UV */ \ + __asm vpunpcklwd ymm0, ymm0, ymm0 /* UVUV (upsample) */ \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpunpckldq ymm0, ymm0, ymm0 /* UVUVUVUV (upsample) */ \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + } + +// Read 8 UV from NV12, upsample to 16 UV. +#define READNV12_AVX2 __asm { \ + __asm vmovdqu xmm0, [esi] /* UV */ \ + __asm lea esi, [esi + 16] \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpunpcklwd ymm0, ymm0, ymm0 /* UVUV (upsample) */ \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + } + +// Read 8 UV from NV21, upsample to 16 UV. +#define READNV21_AVX2 __asm { \ + __asm vmovdqu xmm0, [esi] /* UV */ \ + __asm lea esi, [esi + 16] \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpshufb ymm0, ymm0, ymmword ptr kShuffleNV21 \ + __asm vmovdqu xmm4, [eax] /* Y */ \ + __asm vpermq ymm4, ymm4, 0xd8 \ + __asm vpunpcklbw ymm4, ymm4, ymm4 \ + __asm lea eax, [eax + 16] \ + } + +// Read 8 YUY2 with 16 Y and upsample 8 UV to 16 UV. +#define READYUY2_AVX2 __asm { \ + __asm vmovdqu ymm4, [eax] /* YUY2 */ \ + __asm vpshufb ymm4, ymm4, ymmword ptr kShuffleYUY2Y \ + __asm vmovdqu ymm0, [eax] /* UV */ \ + __asm vpshufb ymm0, ymm0, ymmword ptr kShuffleYUY2UV \ + __asm lea eax, [eax + 32] \ + } + +// Read 8 UYVY with 16 Y and upsample 8 UV to 16 UV. +#define READUYVY_AVX2 __asm { \ + __asm vmovdqu ymm4, [eax] /* UYVY */ \ + __asm vpshufb ymm4, ymm4, ymmword ptr kShuffleUYVYY \ + __asm vmovdqu ymm0, [eax] /* UV */ \ + __asm vpshufb ymm0, ymm0, ymmword ptr kShuffleUYVYUV \ + __asm lea eax, [eax + 32] \ + } + +// Convert 16 pixels: 16 UV and 16 Y. +#define YUVTORGB_AVX2(YuvConstants) __asm { \ + __asm vpmaddubsw ymm2, ymm0, ymmword ptr [YuvConstants + KUVTOR] /* R UV */\ + __asm vpmaddubsw ymm1, ymm0, ymmword ptr [YuvConstants + KUVTOG] /* G UV */\ + __asm vpmaddubsw ymm0, ymm0, ymmword ptr [YuvConstants + KUVTOB] /* B UV */\ + __asm vmovdqu ymm3, ymmword ptr [YuvConstants + KUVBIASR] \ + __asm vpsubw ymm2, ymm3, ymm2 \ + __asm vmovdqu ymm3, ymmword ptr [YuvConstants + KUVBIASG] \ + __asm vpsubw ymm1, ymm3, ymm1 \ + __asm vmovdqu ymm3, ymmword ptr [YuvConstants + KUVBIASB] \ + __asm vpsubw ymm0, ymm3, ymm0 \ + /* Step 2: Find Y contribution to 16 R,G,B values */ \ + __asm vpmulhuw ymm4, ymm4, ymmword ptr [YuvConstants + KYTORGB] \ + __asm vpaddsw ymm0, ymm0, ymm4 /* B += Y */ \ + __asm vpaddsw ymm1, ymm1, ymm4 /* G += Y */ \ + __asm vpaddsw ymm2, ymm2, ymm4 /* R += Y */ \ + __asm vpsraw ymm0, ymm0, 6 \ + __asm vpsraw ymm1, ymm1, 6 \ + __asm vpsraw ymm2, ymm2, 6 \ + __asm vpackuswb ymm0, ymm0, ymm0 /* B */ \ + __asm vpackuswb ymm1, ymm1, ymm1 /* G */ \ + __asm vpackuswb ymm2, ymm2, ymm2 /* R */ \ + } + +// Store 16 ARGB values. +#define STOREARGB_AVX2 __asm { \ + __asm vpunpcklbw ymm0, ymm0, ymm1 /* BG */ \ + __asm vpermq ymm0, ymm0, 0xd8 \ + __asm vpunpcklbw ymm2, ymm2, ymm5 /* RA */ \ + __asm vpermq ymm2, ymm2, 0xd8 \ + __asm vpunpcklwd ymm1, ymm0, ymm2 /* BGRA first 8 pixels */ \ + __asm vpunpckhwd ymm0, ymm0, ymm2 /* BGRA next 8 pixels */ \ + __asm vmovdqu 0[edx], ymm1 \ + __asm vmovdqu 32[edx], ymm0 \ + __asm lea edx, [edx + 64] \ + } + +// Store 16 RGBA values. +#define STORERGBA_AVX2 __asm { \ + __asm vpunpcklbw ymm1, ymm1, ymm2 /* GR */ \ + __asm vpermq ymm1, ymm1, 0xd8 \ + __asm vpunpcklbw ymm2, ymm5, ymm0 /* AB */ \ + __asm vpermq ymm2, ymm2, 0xd8 \ + __asm vpunpcklwd ymm0, ymm2, ymm1 /* ABGR first 8 pixels */ \ + __asm vpunpckhwd ymm1, ymm2, ymm1 /* ABGR next 8 pixels */ \ + __asm vmovdqu [edx], ymm0 \ + __asm vmovdqu [edx + 32], ymm1 \ + __asm lea edx, [edx + 64] \ + } + #ifdef HAS_I422TOARGBROW_AVX2 - -static const lvec8 kUVToB_AVX = { - UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, - UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB, UB, VB -}; -static const lvec8 kUVToR_AVX = { - UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, - UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR, UR, VR -}; -static const lvec8 kUVToG_AVX = { - UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, - UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG -}; -static const lvec16 kYToRgb_AVX = { - YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG -}; -static const lvec16 kYSub16_AVX = { - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -}; -static const lvec16 kUVBiasB_AVX = { - BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB -}; -static const lvec16 kUVBiasG_AVX = { - BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG -}; -static const lvec16 kUVBiasR_AVX = { - BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR -}; - // 16 pixels // 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes). -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I422ToARGBRow_AVX2(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // argb - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha - vpxor ymm4, ymm4, ymm4 - align 4 convertloop: - vmovq xmm0, qword ptr [esi] // U - vmovq xmm1, qword ptr [esi + edi] // V - lea esi, [esi + 8] - vpunpcklbw ymm0, ymm0, ymm1 // UV - vpermq ymm0, ymm0, 0xd8 - vpunpcklwd ymm0, ymm0, ymm0 // UVUV - vpmaddubsw ymm2, ymm0, kUVToB_AVX // scale B UV - vpmaddubsw ymm1, ymm0, kUVToG_AVX // scale G UV - vpmaddubsw ymm0, ymm0, kUVToR_AVX // scale R UV - vpsubw ymm2, ymm2, kUVBiasB_AVX // unbias back to signed - vpsubw ymm1, ymm1, kUVBiasG_AVX - vpsubw ymm0, ymm0, kUVBiasR_AVX + READYUV422_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 - // Step 2: Find Y contribution to 16 R,G,B values - vmovdqu xmm3, [eax] // NOLINT - lea eax, [eax + 16] - vpermq ymm3, ymm3, 0xd8 - vpunpcklbw ymm3, ymm3, ymm4 - vpsubsw ymm3, ymm3, kYSub16_AVX - vpmullw ymm3, ymm3, kYToRgb_AVX - vpaddsw ymm2, ymm2, ymm3 // B += Y - vpaddsw ymm1, ymm1, ymm3 // G += Y - vpaddsw ymm0, ymm0, ymm3 // R += Y - vpsraw ymm2, ymm2, 6 - vpsraw ymm1, ymm1, 6 - vpsraw ymm0, ymm0, 6 - vpackuswb ymm2, ymm2, ymm2 // B - vpackuswb ymm1, ymm1, ymm1 // G - vpackuswb ymm0, ymm0, ymm0 // R - - // Step 3: Weave into ARGB - vpunpcklbw ymm2, ymm2, ymm1 // BG - vpermq ymm2, ymm2, 0xd8 - vpunpcklbw ymm0, ymm0, ymm5 // RA - vpermq ymm0, ymm0, 0xd8 - vpunpcklwd ymm1, ymm2, ymm0 // BGRA first 8 pixels - vpunpckhwd ymm2, ymm2, ymm0 // BGRA next 8 pixels - vmovdqu [edx], ymm1 - vmovdqu [edx + 32], ymm2 - lea edx, [edx + 64] sub ecx, 16 jg convertloop - vzeroupper + pop ebx pop edi pop esi + vzeroupper ret } } #endif // HAS_I422TOARGBROW_AVX2 -#ifdef HAS_I422TOARGBROW_SSSE3 +#ifdef HAS_I422ALPHATOARGBROW_AVX2 +// 16 pixels +// 8 UV values upsampled to 16 UV, mixed with 16 Y and 16 A producing 16 ARGB. +__declspec(naked) +void I422AlphaToARGBRow_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push edi + push ebx + push ebp + mov eax, [esp + 16 + 4] // Y + mov esi, [esp + 16 + 8] // U + mov edi, [esp + 16 + 12] // V + mov ebp, [esp + 16 + 16] // A + mov edx, [esp + 16 + 20] // argb + mov ebx, [esp + 16 + 24] // yuvconstants + mov ecx, [esp + 16 + 28] // width + sub edi, esi + convertloop: + READYUVA422_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebp + pop ebx + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_I422ALPHATOARGBROW_AVX2 + +#ifdef HAS_I444TOARGBROW_AVX2 +// 16 pixels +// 16 UV values with 16 Y producing 16 ARGB (64 bytes). +__declspec(naked) +void I444ToARGBRow_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push edi + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width + sub edi, esi + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + convertloop: + READYUV444_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_I444TOARGBROW_AVX2 + +#ifdef HAS_I411TOARGBROW_AVX2 +// 16 pixels +// 4 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes). +__declspec(naked) +void I411ToARGBRow_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push edi + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // abgr + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width + sub edi, esi + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READYUV411_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_I411TOARGBROW_AVX2 + +#ifdef HAS_NV12TOARGBROW_AVX2 +// 16 pixels. +// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes). +__declspec(naked) +void NV12ToARGBRow_AVX2(const uint8* y_buf, + const uint8* uv_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push ebx + mov eax, [esp + 8 + 4] // Y + mov esi, [esp + 8 + 8] // UV + mov edx, [esp + 8 + 12] // argb + mov ebx, [esp + 8 + 16] // yuvconstants + mov ecx, [esp + 8 + 20] // width + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READNV12_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + pop esi + vzeroupper + ret + } +} +#endif // HAS_NV12TOARGBROW_AVX2 + +#ifdef HAS_NV21TOARGBROW_AVX2 +// 16 pixels. +// 8 VU values upsampled to 16 UV, mixed with 16 Y producing 16 ARGB (64 bytes). +__declspec(naked) +void NV21ToARGBRow_AVX2(const uint8* y_buf, + const uint8* vu_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push ebx + mov eax, [esp + 8 + 4] // Y + mov esi, [esp + 8 + 8] // VU + mov edx, [esp + 8 + 12] // argb + mov ebx, [esp + 8 + 16] // yuvconstants + mov ecx, [esp + 8 + 20] // width + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READNV21_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + pop esi + vzeroupper + ret + } +} +#endif // HAS_NV21TOARGBROW_AVX2 + +#ifdef HAS_YUY2TOARGBROW_AVX2 +// 16 pixels. +// 8 YUY2 values with 16 Y and 8 UV producing 16 ARGB (64 bytes). +__declspec(naked) +void YUY2ToARGBRow_AVX2(const uint8* src_yuy2, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push ebx + mov eax, [esp + 4 + 4] // yuy2 + mov edx, [esp + 4 + 8] // argb + mov ebx, [esp + 4 + 12] // yuvconstants + mov ecx, [esp + 4 + 16] // width + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READYUY2_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + vzeroupper + ret + } +} +#endif // HAS_YUY2TOARGBROW_AVX2 + +#ifdef HAS_UYVYTOARGBROW_AVX2 +// 16 pixels. +// 8 UYVY values with 16 Y and 8 UV producing 16 ARGB (64 bytes). +__declspec(naked) +void UYVYToARGBRow_AVX2(const uint8* src_uyvy, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push ebx + mov eax, [esp + 4 + 4] // uyvy + mov edx, [esp + 4 + 8] // argb + mov ebx, [esp + 4 + 12] // yuvconstants + mov ecx, [esp + 4 + 16] // width + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READUYVY_AVX2 + YUVTORGB_AVX2(ebx) + STOREARGB_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + vzeroupper + ret + } +} +#endif // HAS_UYVYTOARGBROW_AVX2 + +#ifdef HAS_I422TORGBAROW_AVX2 +// 16 pixels +// 8 UV values upsampled to 16 UV, mixed with 16 Y producing 16 RGBA (64 bytes). +__declspec(naked) +void I422ToRGBARow_AVX2(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push edi + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // abgr + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width + sub edi, esi + vpcmpeqb ymm5, ymm5, ymm5 // generate 0xffffffffffffffff for alpha + + convertloop: + READYUV422_AVX2 + YUVTORGB_AVX2(ebx) + STORERGBA_AVX2 + + sub ecx, 16 + jg convertloop + + pop ebx + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_I422TORGBAROW_AVX2 + +#if defined(HAS_I422TOARGBROW_SSSE3) // TODO(fbarchard): Read that does half size on Y and treats 420 as 444. +// Allows a conversion with half size scaling. // Read 8 UV from 444. #define READYUV444 __asm { \ - __asm movq xmm0, qword ptr [esi] /* U */ /* NOLINT */ \ - __asm movq xmm1, qword ptr [esi + edi] /* V */ /* NOLINT */ \ + __asm movq xmm0, qword ptr [esi] /* U */ \ + __asm movq xmm1, qword ptr [esi + edi] /* V */ \ __asm lea esi, [esi + 8] \ __asm punpcklbw xmm0, xmm1 /* UV */ \ + __asm movq xmm4, qword ptr [eax] \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ } // Read 4 UV from 422, upsample to 8 UV. @@ -2314,47 +2424,99 @@ void I422ToARGBRow_AVX2(const uint8* y_buf, __asm lea esi, [esi + 4] \ __asm punpcklbw xmm0, xmm1 /* UV */ \ __asm punpcklwd xmm0, xmm0 /* UVUV (upsample) */ \ + __asm movq xmm4, qword ptr [eax] \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ + } + +// Read 4 UV from 422, upsample to 8 UV. With 8 Alpha. +#define READYUVA422 __asm { \ + __asm movd xmm0, [esi] /* U */ \ + __asm movd xmm1, [esi + edi] /* V */ \ + __asm lea esi, [esi + 4] \ + __asm punpcklbw xmm0, xmm1 /* UV */ \ + __asm punpcklwd xmm0, xmm0 /* UVUV (upsample) */ \ + __asm movq xmm4, qword ptr [eax] /* Y */ \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ + __asm movq xmm5, qword ptr [ebp] /* A */ \ + __asm lea ebp, [ebp + 8] \ } // Read 2 UV from 411, upsample to 8 UV. -#define READYUV411 __asm { \ - __asm movzx ebx, word ptr [esi] /* U */ /* NOLINT */ \ +// drmemory fails with memory fault if pinsrw used. libyuv bug: 525 +// __asm pinsrw xmm0, [esi], 0 /* U */ +// __asm pinsrw xmm1, [esi + edi], 0 /* V */ +#define READYUV411_EBX __asm { \ + __asm movzx ebx, word ptr [esi] /* U */ \ __asm movd xmm0, ebx \ - __asm movzx ebx, word ptr [esi + edi] /* V */ /* NOLINT */ \ + __asm movzx ebx, word ptr [esi + edi] /* V */ \ __asm movd xmm1, ebx \ __asm lea esi, [esi + 2] \ - __asm punpcklbw xmm0, xmm1 /* UV */ \ - __asm punpcklwd xmm0, xmm0 /* UVUV (upsample) */ \ - __asm punpckldq xmm0, xmm0 /* UVUV (upsample) */ \ + __asm punpcklbw xmm0, xmm1 /* UV */ \ + __asm punpcklwd xmm0, xmm0 /* UVUV (upsample) */ \ + __asm punpckldq xmm0, xmm0 /* UVUVUVUV (upsample) */ \ + __asm movq xmm4, qword ptr [eax] \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ } // Read 4 UV from NV12, upsample to 8 UV. #define READNV12 __asm { \ - __asm movq xmm0, qword ptr [esi] /* UV */ /* NOLINT */ \ + __asm movq xmm0, qword ptr [esi] /* UV */ \ __asm lea esi, [esi + 8] \ __asm punpcklwd xmm0, xmm0 /* UVUV (upsample) */ \ + __asm movq xmm4, qword ptr [eax] \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ + } + +// Read 4 VU from NV21, upsample to 8 UV. +#define READNV21 __asm { \ + __asm movq xmm0, qword ptr [esi] /* UV */ \ + __asm lea esi, [esi + 8] \ + __asm pshufb xmm0, xmmword ptr kShuffleNV21 \ + __asm movq xmm4, qword ptr [eax] \ + __asm punpcklbw xmm4, xmm4 \ + __asm lea eax, [eax + 8] \ + } + +// Read 4 YUY2 with 8 Y and upsample 4 UV to 8 UV. +#define READYUY2 __asm { \ + __asm movdqu xmm4, [eax] /* YUY2 */ \ + __asm pshufb xmm4, xmmword ptr kShuffleYUY2Y \ + __asm movdqu xmm0, [eax] /* UV */ \ + __asm pshufb xmm0, xmmword ptr kShuffleYUY2UV \ + __asm lea eax, [eax + 16] \ + } + +// Read 4 UYVY with 8 Y and upsample 4 UV to 8 UV. +#define READUYVY __asm { \ + __asm movdqu xmm4, [eax] /* UYVY */ \ + __asm pshufb xmm4, xmmword ptr kShuffleUYVYY \ + __asm movdqu xmm0, [eax] /* UV */ \ + __asm pshufb xmm0, xmmword ptr kShuffleUYVYUV \ + __asm lea eax, [eax + 16] \ } // Convert 8 pixels: 8 UV and 8 Y. -#define YUVTORGB __asm { \ - /* Step 1: Find 4 UV contributions to 8 R,G,B values */ \ +#define YUVTORGB(YuvConstants) __asm { \ __asm movdqa xmm1, xmm0 \ __asm movdqa xmm2, xmm0 \ - __asm pmaddubsw xmm0, kUVToB /* scale B UV */ \ - __asm pmaddubsw xmm1, kUVToG /* scale G UV */ \ - __asm pmaddubsw xmm2, kUVToR /* scale R UV */ \ - __asm psubw xmm0, kUVBiasB /* unbias back to signed */ \ - __asm psubw xmm1, kUVBiasG \ - __asm psubw xmm2, kUVBiasR \ - /* Step 2: Find Y contribution to 8 R,G,B values */ \ - __asm movq xmm3, qword ptr [eax] /* NOLINT */ \ - __asm lea eax, [eax + 8] \ - __asm punpcklbw xmm3, xmm4 \ - __asm psubsw xmm3, kYSub16 \ - __asm pmullw xmm3, kYToRgb \ - __asm paddsw xmm0, xmm3 /* B += Y */ \ - __asm paddsw xmm1, xmm3 /* G += Y */ \ - __asm paddsw xmm2, xmm3 /* R += Y */ \ + __asm movdqa xmm3, xmm0 \ + __asm movdqa xmm0, xmmword ptr [YuvConstants + KUVBIASB] \ + __asm pmaddubsw xmm1, xmmword ptr [YuvConstants + KUVTOB] \ + __asm psubw xmm0, xmm1 \ + __asm movdqa xmm1, xmmword ptr [YuvConstants + KUVBIASG] \ + __asm pmaddubsw xmm2, xmmword ptr [YuvConstants + KUVTOG] \ + __asm psubw xmm1, xmm2 \ + __asm movdqa xmm2, xmmword ptr [YuvConstants + KUVBIASR] \ + __asm pmaddubsw xmm3, xmmword ptr [YuvConstants + KUVTOR] \ + __asm psubw xmm2, xmm3 \ + __asm pmulhuw xmm4, xmmword ptr [YuvConstants + KYTORGB] \ + __asm paddsw xmm0, xmm4 /* B += Y */ \ + __asm paddsw xmm1, xmm4 /* G += Y */ \ + __asm paddsw xmm2, xmm4 /* R += Y */ \ __asm psraw xmm0, 6 \ __asm psraw xmm1, 6 \ __asm psraw xmm2, 6 \ @@ -2363,189 +2525,192 @@ void I422ToARGBRow_AVX2(const uint8* y_buf, __asm packuswb xmm2, xmm2 /* R */ \ } -// Convert 8 pixels: 8 VU and 8 Y. -#define YVUTORGB __asm { \ - /* Step 1: Find 4 UV contributions to 8 R,G,B values */ \ +// Store 8 ARGB values. +#define STOREARGB __asm { \ + __asm punpcklbw xmm0, xmm1 /* BG */ \ + __asm punpcklbw xmm2, xmm5 /* RA */ \ __asm movdqa xmm1, xmm0 \ - __asm movdqa xmm2, xmm0 \ - __asm pmaddubsw xmm0, kVUToB /* scale B UV */ \ - __asm pmaddubsw xmm1, kVUToG /* scale G UV */ \ - __asm pmaddubsw xmm2, kVUToR /* scale R UV */ \ - __asm psubw xmm0, kUVBiasB /* unbias back to signed */ \ - __asm psubw xmm1, kUVBiasG \ - __asm psubw xmm2, kUVBiasR \ - /* Step 2: Find Y contribution to 8 R,G,B values */ \ - __asm movq xmm3, qword ptr [eax] /* NOLINT */ \ - __asm lea eax, [eax + 8] \ - __asm punpcklbw xmm3, xmm4 \ - __asm psubsw xmm3, kYSub16 \ - __asm pmullw xmm3, kYToRgb \ - __asm paddsw xmm0, xmm3 /* B += Y */ \ - __asm paddsw xmm1, xmm3 /* G += Y */ \ - __asm paddsw xmm2, xmm3 /* R += Y */ \ - __asm psraw xmm0, 6 \ - __asm psraw xmm1, 6 \ - __asm psraw xmm2, 6 \ - __asm packuswb xmm0, xmm0 /* B */ \ - __asm packuswb xmm1, xmm1 /* G */ \ - __asm packuswb xmm2, xmm2 /* R */ \ + __asm punpcklwd xmm0, xmm2 /* BGRA first 4 pixels */ \ + __asm punpckhwd xmm1, xmm2 /* BGRA next 4 pixels */ \ + __asm movdqu 0[edx], xmm0 \ + __asm movdqu 16[edx], xmm1 \ + __asm lea edx, [edx + 32] \ } -// 8 pixels, dest aligned 16. +// Store 8 BGRA values. +#define STOREBGRA __asm { \ + __asm pcmpeqb xmm5, xmm5 /* generate 0xffffffff for alpha */ \ + __asm punpcklbw xmm1, xmm0 /* GB */ \ + __asm punpcklbw xmm5, xmm2 /* AR */ \ + __asm movdqa xmm0, xmm5 \ + __asm punpcklwd xmm5, xmm1 /* BGRA first 4 pixels */ \ + __asm punpckhwd xmm0, xmm1 /* BGRA next 4 pixels */ \ + __asm movdqu 0[edx], xmm5 \ + __asm movdqu 16[edx], xmm0 \ + __asm lea edx, [edx + 32] \ + } + +// Store 8 RGBA values. +#define STORERGBA __asm { \ + __asm pcmpeqb xmm5, xmm5 /* generate 0xffffffff for alpha */ \ + __asm punpcklbw xmm1, xmm2 /* GR */ \ + __asm punpcklbw xmm5, xmm0 /* AB */ \ + __asm movdqa xmm0, xmm5 \ + __asm punpcklwd xmm5, xmm1 /* RGBA first 4 pixels */ \ + __asm punpckhwd xmm0, xmm1 /* RGBA next 4 pixels */ \ + __asm movdqu 0[edx], xmm5 \ + __asm movdqu 16[edx], xmm0 \ + __asm lea edx, [edx + 32] \ + } + +// Store 8 RGB24 values. +#define STORERGB24 __asm { \ + /* Weave into RRGB */ \ + __asm punpcklbw xmm0, xmm1 /* BG */ \ + __asm punpcklbw xmm2, xmm2 /* RR */ \ + __asm movdqa xmm1, xmm0 \ + __asm punpcklwd xmm0, xmm2 /* BGRR first 4 pixels */ \ + __asm punpckhwd xmm1, xmm2 /* BGRR next 4 pixels */ \ + /* RRGB -> RGB24 */ \ + __asm pshufb xmm0, xmm5 /* Pack first 8 and last 4 bytes. */ \ + __asm pshufb xmm1, xmm6 /* Pack first 12 bytes. */ \ + __asm palignr xmm1, xmm0, 12 /* last 4 bytes of xmm0 + 12 xmm1 */ \ + __asm movq qword ptr 0[edx], xmm0 /* First 8 bytes */ \ + __asm movdqu 8[edx], xmm1 /* Last 16 bytes */ \ + __asm lea edx, [edx + 24] \ + } + +// Store 8 RGB565 values. +#define STORERGB565 __asm { \ + /* Weave into RRGB */ \ + __asm punpcklbw xmm0, xmm1 /* BG */ \ + __asm punpcklbw xmm2, xmm2 /* RR */ \ + __asm movdqa xmm1, xmm0 \ + __asm punpcklwd xmm0, xmm2 /* BGRR first 4 pixels */ \ + __asm punpckhwd xmm1, xmm2 /* BGRR next 4 pixels */ \ + /* RRGB -> RGB565 */ \ + __asm movdqa xmm3, xmm0 /* B first 4 pixels of argb */ \ + __asm movdqa xmm2, xmm0 /* G */ \ + __asm pslld xmm0, 8 /* R */ \ + __asm psrld xmm3, 3 /* B */ \ + __asm psrld xmm2, 5 /* G */ \ + __asm psrad xmm0, 16 /* R */ \ + __asm pand xmm3, xmm5 /* B */ \ + __asm pand xmm2, xmm6 /* G */ \ + __asm pand xmm0, xmm7 /* R */ \ + __asm por xmm3, xmm2 /* BG */ \ + __asm por xmm0, xmm3 /* BGR */ \ + __asm movdqa xmm3, xmm1 /* B next 4 pixels of argb */ \ + __asm movdqa xmm2, xmm1 /* G */ \ + __asm pslld xmm1, 8 /* R */ \ + __asm psrld xmm3, 3 /* B */ \ + __asm psrld xmm2, 5 /* G */ \ + __asm psrad xmm1, 16 /* R */ \ + __asm pand xmm3, xmm5 /* B */ \ + __asm pand xmm2, xmm6 /* G */ \ + __asm pand xmm1, xmm7 /* R */ \ + __asm por xmm3, xmm2 /* BG */ \ + __asm por xmm1, xmm3 /* BGR */ \ + __asm packssdw xmm0, xmm1 \ + __asm movdqu 0[edx], xmm0 /* store 8 pixels of RGB565 */ \ + __asm lea edx, [edx + 16] \ + } + +// 8 pixels. // 8 UV values, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I444ToARGBRow_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // argb - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 + pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - align 4 convertloop: READYUV444 - YUVTORGB + YUVTORGB(ebx) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop + pop ebx pop edi pop esi ret } } -// 8 pixels, dest aligned 16. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +// 8 pixels. +// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 RGB24 (24 bytes). +__declspec(naked) void I422ToRGB24Row_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_rgb24, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // rgb24 - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi - pxor xmm4, xmm4 - movdqa xmm5, kShuffleMaskARGBToRGB24_0 - movdqa xmm6, kShuffleMaskARGBToRGB24 + movdqa xmm5, xmmword ptr kShuffleMaskARGBToRGB24_0 + movdqa xmm6, xmmword ptr kShuffleMaskARGBToRGB24 - align 4 convertloop: READYUV422 - YUVTORGB + YUVTORGB(ebx) + STORERGB24 - // Step 3: Weave into RRGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm2 // RR - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRR first 4 pixels - punpckhwd xmm1, xmm2 // BGRR next 4 pixels - pshufb xmm0, xmm5 // Pack into first 8 and last 4 bytes. - pshufb xmm1, xmm6 // Pack into first 12 bytes. - palignr xmm1, xmm0, 12 // last 4 bytes of xmm0 + 12 from xmm1 - movq qword ptr [edx], xmm0 // First 8 bytes - movdqu [edx + 8], xmm1 // Last 16 bytes. = 24 bytes, 8 RGB pixels. - lea edx, [edx + 24] sub ecx, 8 jg convertloop + pop ebx pop edi pop esi ret } } -// 8 pixels, dest aligned 16. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) -void I422ToRAWRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_raw, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // raw - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pxor xmm4, xmm4 - movdqa xmm5, kShuffleMaskARGBToRAW_0 - movdqa xmm6, kShuffleMaskARGBToRAW - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into RRGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm2 // RR - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRR first 4 pixels - punpckhwd xmm1, xmm2 // BGRR next 4 pixels - pshufb xmm0, xmm5 // Pack into first 8 and last 4 bytes. - pshufb xmm1, xmm6 // Pack into first 12 bytes. - palignr xmm1, xmm0, 12 // last 4 bytes of xmm0 + 12 from xmm1 - movq qword ptr [edx], xmm0 // First 8 bytes - movdqu [edx + 8], xmm1 // Last 16 bytes. = 24 bytes, 8 RGB pixels. - lea edx, [edx + 24] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - -// 8 pixels, dest unaligned. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +// 8 pixels +// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 RGB565 (16 bytes). +__declspec(naked) void I422ToRGB565Row_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* rgb565_buf, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // rgb565 - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi - pxor xmm4, xmm4 pcmpeqb xmm5, xmm5 // generate mask 0x0000001f psrld xmm5, 27 pcmpeqb xmm6, xmm6 // generate mask 0x000007e0 @@ -2554,701 +2719,320 @@ void I422ToRGB565Row_SSSE3(const uint8* y_buf, pcmpeqb xmm7, xmm7 // generate mask 0xfffff800 pslld xmm7, 11 - align 4 convertloop: READYUV422 - YUVTORGB + YUVTORGB(ebx) + STORERGB565 - // Step 3: Weave into RRGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm2 // RR - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRR first 4 pixels - punpckhwd xmm1, xmm2 // BGRR next 4 pixels - - // Step 3b: RRGB -> RGB565 - movdqa xmm3, xmm0 // B first 4 pixels of argb - movdqa xmm2, xmm0 // G - pslld xmm0, 8 // R - psrld xmm3, 3 // B - psrld xmm2, 5 // G - psrad xmm0, 16 // R - pand xmm3, xmm5 // B - pand xmm2, xmm6 // G - pand xmm0, xmm7 // R - por xmm3, xmm2 // BG - por xmm0, xmm3 // BGR - movdqa xmm3, xmm1 // B next 4 pixels of argb - movdqa xmm2, xmm1 // G - pslld xmm1, 8 // R - psrld xmm3, 3 // B - psrld xmm2, 5 // G - psrad xmm1, 16 // R - pand xmm3, xmm5 // B - pand xmm2, xmm6 // G - pand xmm1, xmm7 // R - por xmm3, xmm2 // BG - por xmm1, xmm3 // BGR - packssdw xmm0, xmm1 sub ecx, 8 - movdqu [edx], xmm0 // store 8 pixels of RGB565 - lea edx, [edx + 16] jg convertloop + pop ebx pop edi pop esi ret } } -// 8 pixels, dest aligned 16. +// 8 pixels. // 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I422ToARGBRow_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // argb - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - align 4 convertloop: READYUV422 - YUVTORGB + YUVTORGB(ebx) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop + pop ebx pop edi pop esi ret } } -// 8 pixels, dest aligned 16. +// 8 pixels. +// 4 UV values upsampled to 8 UV, mixed with 8 Y and 8 A producing 8 ARGB. +__declspec(naked) +void I422AlphaToARGBRow_SSSE3(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + const uint8* a_buf, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + __asm { + push esi + push edi + push ebx + push ebp + mov eax, [esp + 16 + 4] // Y + mov esi, [esp + 16 + 8] // U + mov edi, [esp + 16 + 12] // V + mov ebp, [esp + 16 + 16] // A + mov edx, [esp + 16 + 20] // argb + mov ebx, [esp + 16 + 24] // yuvconstants + mov ecx, [esp + 16 + 28] // width + sub edi, esi + + convertloop: + READYUVA422 + YUVTORGB(ebx) + STOREARGB + + sub ecx, 8 + jg convertloop + + pop ebp + pop ebx + pop edi + pop esi + ret + } +} + +// 8 pixels. // 2 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). // Similar to I420 but duplicate UV once more. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I411ToARGBRow_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { - push ebx push esi push edi - mov eax, [esp + 12 + 4] // Y - mov esi, [esp + 12 + 8] // U - mov edi, [esp + 12 + 12] // V - mov edx, [esp + 12 + 16] // argb - mov ecx, [esp + 12 + 20] // width + push ebx + push ebp + mov eax, [esp + 16 + 4] // Y + mov esi, [esp + 16 + 8] // U + mov edi, [esp + 16 + 12] // V + mov edx, [esp + 16 + 16] // abgr + mov ebp, [esp + 16 + 20] // yuvconstants + mov ecx, [esp + 16 + 24] // width sub edi, esi - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 + pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - align 4 convertloop: - READYUV411 // modifies EBX - YUVTORGB + READYUV411_EBX + YUVTORGB(ebp) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop + pop ebp + pop ebx pop edi pop esi - pop ebx ret } } -// 8 pixels, dest aligned 16. +// 8 pixels. // 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +__declspec(naked) void NV12ToARGBRow_SSSE3(const uint8* y_buf, const uint8* uv_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi - mov eax, [esp + 4 + 4] // Y - mov esi, [esp + 4 + 8] // UV - mov edx, [esp + 4 + 12] // argb - mov ecx, [esp + 4 + 16] // width + push ebx + mov eax, [esp + 8 + 4] // Y + mov esi, [esp + 8 + 8] // UV + mov edx, [esp + 8 + 12] // argb + mov ebx, [esp + 8 + 16] // yuvconstants + mov ecx, [esp + 8 + 20] // width pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - align 4 convertloop: READNV12 - YUVTORGB + YUVTORGB(ebx) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop + pop ebx pop esi ret } } -// 8 pixels, dest aligned 16. +// 8 pixels. // 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) +__declspec(naked) void NV21ToARGBRow_SSSE3(const uint8* y_buf, - const uint8* uv_buf, + const uint8* vu_buf, uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi - mov eax, [esp + 4 + 4] // Y - mov esi, [esp + 4 + 8] // VU - mov edx, [esp + 4 + 12] // argb - mov ecx, [esp + 4 + 16] // width - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READNV12 - YVUTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop esi - ret - } -} - -// 8 pixels, unaligned. -// 8 UV values, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) -void I444ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - __asm { - push esi - push edi + push ebx mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // argb + mov esi, [esp + 8 + 8] // VU + mov edx, [esp + 8 + 12] // argb + mov ebx, [esp + 8 + 16] // yuvconstants mov ecx, [esp + 8 + 20] // width - sub edi, esi pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - align 4 convertloop: - READYUV444 - YUVTORGB + READNV21 + YUVTORGB(ebx) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqu [edx], xmm0 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop - pop edi + pop ebx pop esi ret } } -// 8 pixels, unaligned. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) -void I422ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // argb - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqu [edx], xmm0 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - -// 8 pixels, unaligned. -// 2 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -// Similar to I420 but duplicate UV once more. -__declspec(naked) __declspec(align(16)) -void I411ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_argb, - int width) { +// 8 pixels. +// 4 YUY2 values with 8 Y and 4 UV producing 8 ARGB (32 bytes). +__declspec(naked) +void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { __asm { push ebx - push esi - push edi - mov eax, [esp + 12 + 4] // Y - mov esi, [esp + 12 + 8] // U - mov edi, [esp + 12 + 12] // V - mov edx, [esp + 12 + 16] // argb - mov ecx, [esp + 12 + 20] // width - sub edi, esi + mov eax, [esp + 4 + 4] // yuy2 + mov edx, [esp + 4 + 8] // argb + mov ebx, [esp + 4 + 12] // yuvconstants + mov ecx, [esp + 4 + 16] // width pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - align 4 convertloop: - READYUV411 // modifies EBX - YUVTORGB + READYUY2 + YUVTORGB(ebx) + STOREARGB - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqu [edx], xmm0 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] sub ecx, 8 jg convertloop - pop edi - pop esi pop ebx ret } } -// 8 pixels, dest aligned 16. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) -void NV12ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - __asm { - push esi - mov eax, [esp + 4 + 4] // Y - mov esi, [esp + 4 + 8] // UV - mov edx, [esp + 4 + 12] // argb - mov ecx, [esp + 4 + 16] // width - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READNV12 - YUVTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqu [edx], xmm0 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop esi - ret - } -} - -// 8 pixels, dest aligned 16. -// 4 UV values upsampled to 8 UV, mixed with 8 Y producing 8 ARGB (32 bytes). -__declspec(naked) __declspec(align(16)) -void NV21ToARGBRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* uv_buf, - uint8* dst_argb, - int width) { - __asm { - push esi - mov eax, [esp + 4 + 4] // Y - mov esi, [esp + 4 + 8] // VU - mov edx, [esp + 4 + 12] // argb - mov ecx, [esp + 4 + 16] // width - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READNV12 - YVUTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm0, xmm1 // BG - punpcklbw xmm2, xmm5 // RA - movdqa xmm1, xmm0 - punpcklwd xmm0, xmm2 // BGRA first 4 pixels - punpckhwd xmm1, xmm2 // BGRA next 4 pixels - movdqu [edx], xmm0 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void I422ToBGRARow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_bgra, +// 8 pixels. +// 4 UYVY values with 8 Y and 4 UV producing 8 ARGB (32 bytes). +__declspec(naked) +void UYVYToARGBRow_SSSE3(const uint8* src_uyvy, + uint8* dst_argb, + const struct YuvConstants* yuvconstants, int width) { __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // bgra - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into BGRA + push ebx + mov eax, [esp + 4 + 4] // uyvy + mov edx, [esp + 4 + 8] // argb + mov ebx, [esp + 4 + 12] // yuvconstants + mov ecx, [esp + 4 + 16] // width pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - punpcklbw xmm1, xmm0 // GB - punpcklbw xmm5, xmm2 // AR - movdqa xmm0, xmm5 - punpcklwd xmm5, xmm1 // BGRA first 4 pixels - punpckhwd xmm0, xmm1 // BGRA next 4 pixels - movdqa [edx], xmm5 - movdqa [edx + 16], xmm0 - lea edx, [edx + 32] + + convertloop: + READUYVY + YUVTORGB(ebx) + STOREARGB + sub ecx, 8 jg convertloop - pop edi - pop esi + pop ebx ret } } -__declspec(naked) __declspec(align(16)) -void I422ToBGRARow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_bgra, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // bgra - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into BGRA - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - punpcklbw xmm1, xmm0 // GB - punpcklbw xmm5, xmm2 // AR - movdqa xmm0, xmm5 - punpcklwd xmm5, xmm1 // BGRA first 4 pixels - punpckhwd xmm0, xmm1 // BGRA next 4 pixels - movdqu [edx], xmm5 - movdqu [edx + 16], xmm0 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void I422ToABGRRow_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_abgr, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // abgr - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm2, xmm1 // RG - punpcklbw xmm0, xmm5 // BA - movdqa xmm1, xmm2 - punpcklwd xmm2, xmm0 // RGBA first 4 pixels - punpckhwd xmm1, xmm0 // RGBA next 4 pixels - movdqa [edx], xmm2 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void I422ToABGRRow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_abgr, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // abgr - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into ARGB - punpcklbw xmm2, xmm1 // RG - punpcklbw xmm0, xmm5 // BA - movdqa xmm1, xmm2 - punpcklwd xmm2, xmm0 // RGBA first 4 pixels - punpckhwd xmm1, xmm0 // RGBA next 4 pixels - movdqu [edx], xmm2 - movdqu [edx + 16], xmm1 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I422ToRGBARow_SSSE3(const uint8* y_buf, const uint8* u_buf, const uint8* v_buf, uint8* dst_rgba, + const struct YuvConstants* yuvconstants, int width) { __asm { push esi push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // rgba - mov ecx, [esp + 8 + 20] // width + push ebx + mov eax, [esp + 12 + 4] // Y + mov esi, [esp + 12 + 8] // U + mov edi, [esp + 12 + 12] // V + mov edx, [esp + 12 + 16] // argb + mov ebx, [esp + 12 + 20] // yuvconstants + mov ecx, [esp + 12 + 24] // width sub edi, esi - pxor xmm4, xmm4 - align 4 convertloop: READYUV422 - YUVTORGB + YUVTORGB(ebx) + STORERGBA - // Step 3: Weave into RGBA - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - punpcklbw xmm1, xmm2 // GR - punpcklbw xmm5, xmm0 // AB - movdqa xmm0, xmm5 - punpcklwd xmm5, xmm1 // RGBA first 4 pixels - punpckhwd xmm0, xmm1 // RGBA next 4 pixels - movdqa [edx], xmm5 - movdqa [edx + 16], xmm0 - lea edx, [edx + 32] sub ecx, 8 jg convertloop + pop ebx pop edi pop esi ret } } - -__declspec(naked) __declspec(align(16)) -void I422ToRGBARow_Unaligned_SSSE3(const uint8* y_buf, - const uint8* u_buf, - const uint8* v_buf, - uint8* dst_rgba, - int width) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // Y - mov esi, [esp + 8 + 8] // U - mov edi, [esp + 8 + 12] // V - mov edx, [esp + 8 + 16] // rgba - mov ecx, [esp + 8 + 20] // width - sub edi, esi - pxor xmm4, xmm4 - - align 4 - convertloop: - READYUV422 - YUVTORGB - - // Step 3: Weave into RGBA - pcmpeqb xmm5, xmm5 // generate 0xffffffff for alpha - punpcklbw xmm1, xmm2 // GR - punpcklbw xmm5, xmm0 // AB - movdqa xmm0, xmm5 - punpcklwd xmm5, xmm1 // RGBA first 4 pixels - punpckhwd xmm0, xmm1 // RGBA next 4 pixels - movdqu [edx], xmm5 - movdqu [edx + 16], xmm0 - lea edx, [edx + 32] - sub ecx, 8 - jg convertloop - - pop edi - pop esi - ret - } -} - #endif // HAS_I422TOARGBROW_SSSE3 -#ifdef HAS_YTOARGBROW_SSE2 -__declspec(naked) __declspec(align(16)) -void YToARGBRow_SSE2(const uint8* y_buf, - uint8* rgb_buf, - int width) { +#ifdef HAS_I400TOARGBROW_SSE2 +// 8 pixels of Y converted to 8 pixels of ARGB (32 bytes). +__declspec(naked) +void I400ToARGBRow_SSE2(const uint8* y_buf, + uint8* rgb_buf, + int width) { __asm { - pxor xmm5, xmm5 - pcmpeqb xmm4, xmm4 // generate mask 0xff000000 - pslld xmm4, 24 - mov eax, 0x00100010 - movd xmm3, eax - pshufd xmm3, xmm3, 0 - mov eax, 0x004a004a // 74 + mov eax, 0x4a354a35 // 4a35 = 18997 = round(1.164 * 64 * 256) movd xmm2, eax pshufd xmm2, xmm2,0 + mov eax, 0x04880488 // 0488 = 1160 = round(1.164 * 64 * 16) + movd xmm3, eax + pshufd xmm3, xmm3, 0 + pcmpeqb xmm4, xmm4 // generate mask 0xff000000 + pslld xmm4, 24 + mov eax, [esp + 4] // Y mov edx, [esp + 8] // rgb mov ecx, [esp + 12] // width - align 4 convertloop: // Step 1: Scale Y contribution to 8 G values. G = (y - 16) * 1.164 movq xmm0, qword ptr [eax] lea eax, [eax + 8] - punpcklbw xmm0, xmm5 // 0.Y + punpcklbw xmm0, xmm0 // Y.Y + pmulhuw xmm0, xmm2 psubusw xmm0, xmm3 - pmullw xmm0, xmm2 psrlw xmm0, 6 packuswb xmm0, xmm0 // G @@ -3259,16 +3043,66 @@ void YToARGBRow_SSE2(const uint8* y_buf, punpckhwd xmm1, xmm1 // BGRA next 4 pixels por xmm0, xmm4 por xmm1, xmm4 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 + movdqu [edx], xmm0 + movdqu [edx + 16], xmm1 lea edx, [edx + 32] sub ecx, 8 jg convertloop - ret } } -#endif // HAS_YTOARGBROW_SSE2 +#endif // HAS_I400TOARGBROW_SSE2 + +#ifdef HAS_I400TOARGBROW_AVX2 +// 16 pixels of Y converted to 16 pixels of ARGB (64 bytes). +// note: vpunpcklbw mutates and vpackuswb unmutates. +__declspec(naked) +void I400ToARGBRow_AVX2(const uint8* y_buf, + uint8* rgb_buf, + int width) { + __asm { + mov eax, 0x4a354a35 // 4a35 = 18997 = round(1.164 * 64 * 256) + vmovd xmm2, eax + vbroadcastss ymm2, xmm2 + mov eax, 0x04880488 // 0488 = 1160 = round(1.164 * 64 * 16) + vmovd xmm3, eax + vbroadcastss ymm3, xmm3 + vpcmpeqb ymm4, ymm4, ymm4 // generate mask 0xff000000 + vpslld ymm4, ymm4, 24 + + mov eax, [esp + 4] // Y + mov edx, [esp + 8] // rgb + mov ecx, [esp + 12] // width + + convertloop: + // Step 1: Scale Y contriportbution to 16 G values. G = (y - 16) * 1.164 + vmovdqu xmm0, [eax] + lea eax, [eax + 16] + vpermq ymm0, ymm0, 0xd8 // vpunpcklbw mutates + vpunpcklbw ymm0, ymm0, ymm0 // Y.Y + vpmulhuw ymm0, ymm0, ymm2 + vpsubusw ymm0, ymm0, ymm3 + vpsrlw ymm0, ymm0, 6 + vpackuswb ymm0, ymm0, ymm0 // G. still mutated: 3120 + + // TODO(fbarchard): Weave alpha with unpack. + // Step 2: Weave into ARGB + vpunpcklbw ymm1, ymm0, ymm0 // GG - mutates + vpermq ymm1, ymm1, 0xd8 + vpunpcklwd ymm0, ymm1, ymm1 // GGGG first 8 pixels + vpunpckhwd ymm1, ymm1, ymm1 // GGGG next 8 pixels + vpor ymm0, ymm0, ymm4 + vpor ymm1, ymm1, ymm4 + vmovdqu [edx], ymm0 + vmovdqu [edx + 32], ymm1 + lea edx, [edx + 64] + sub ecx, 16 + jg convertloop + vzeroupper + ret + } +} +#endif // HAS_I400TOARGBROW_AVX2 #ifdef HAS_MIRRORROW_SSSE3 // Shuffle table for reversing the bytes. @@ -3276,22 +3110,21 @@ static const uvec8 kShuffleMirror = { 15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u }; -__declspec(naked) __declspec(align(16)) +// TODO(fbarchard): Replace lea with -16 offset. +__declspec(naked) void MirrorRow_SSSE3(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src mov edx, [esp + 8] // dst mov ecx, [esp + 12] // width - movdqa xmm5, kShuffleMirror - lea eax, [eax - 16] + movdqa xmm5, xmmword ptr kShuffleMirror - align 4 convertloop: - movdqa xmm0, [eax + ecx] + movdqu xmm0, [eax - 16 + ecx] pshufb xmm0, xmm5 - sub ecx, 16 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop ret } @@ -3299,29 +3132,21 @@ void MirrorRow_SSSE3(const uint8* src, uint8* dst, int width) { #endif // HAS_MIRRORROW_SSSE3 #ifdef HAS_MIRRORROW_AVX2 -// Shuffle table for reversing the bytes. -static const ulvec8 kShuffleMirror_AVX2 = { - 15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u, - 15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u -}; - -__declspec(naked) __declspec(align(16)) +__declspec(naked) void MirrorRow_AVX2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src mov edx, [esp + 8] // dst mov ecx, [esp + 12] // width - vmovdqa ymm5, kShuffleMirror_AVX2 - lea eax, [eax - 32] + vbroadcastf128 ymm5, xmmword ptr kShuffleMirror - align 4 convertloop: - vmovdqu ymm0, [eax + ecx] + vmovdqu ymm0, [eax - 32 + ecx] vpshufb ymm0, ymm0, ymm5 vpermq ymm0, ymm0, 0x4e // swap high and low halfs - sub ecx, 32 vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 32 jg convertloop vzeroupper ret @@ -3329,43 +3154,13 @@ void MirrorRow_AVX2(const uint8* src, uint8* dst, int width) { } #endif // HAS_MIRRORROW_AVX2 -#ifdef HAS_MIRRORROW_SSE2 -// SSE2 version has movdqu so it can be used on unaligned buffers when SSSE3 -// version can not. -__declspec(naked) __declspec(align(16)) -void MirrorRow_SSE2(const uint8* src, uint8* dst, int width) { - __asm { - mov eax, [esp + 4] // src - mov edx, [esp + 8] // dst - mov ecx, [esp + 12] // width - lea eax, [eax - 16] - - align 4 - convertloop: - movdqu xmm0, [eax + ecx] - movdqa xmm1, xmm0 // swap bytes - psllw xmm0, 8 - psrlw xmm1, 8 - por xmm0, xmm1 - pshuflw xmm0, xmm0, 0x1b // swap words - pshufhw xmm0, xmm0, 0x1b - pshufd xmm0, xmm0, 0x4e // swap qwords - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - ret - } -} -#endif // HAS_MIRRORROW_SSE2 - #ifdef HAS_MIRRORROW_UV_SSSE3 // Shuffle table for reversing the bytes of UV channels. static const uvec8 kShuffleMirrorUV = { 14u, 12u, 10u, 8u, 6u, 4u, 2u, 0u, 15u, 13u, 11u, 9u, 7u, 5u, 3u, 1u }; -__declspec(naked) __declspec(align(16)) +__declspec(naked) void MirrorUVRow_SSSE3(const uint8* src, uint8* dst_u, uint8* dst_v, int width) { __asm { @@ -3374,19 +3169,18 @@ void MirrorUVRow_SSSE3(const uint8* src, uint8* dst_u, uint8* dst_v, mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v mov ecx, [esp + 4 + 16] // width - movdqa xmm1, kShuffleMirrorUV + movdqa xmm1, xmmword ptr kShuffleMirrorUV lea eax, [eax + ecx * 2 - 16] sub edi, edx - align 4 convertloop: - movdqa xmm0, [eax] + movdqu xmm0, [eax] lea eax, [eax - 16] pshufb xmm0, xmm1 - sub ecx, 8 movlpd qword ptr [edx], xmm0 movhpd qword ptr [edx + edi], xmm0 lea edx, [edx + 8] + sub ecx, 8 jg convertloop pop edi @@ -3395,34 +3189,27 @@ void MirrorUVRow_SSSE3(const uint8* src, uint8* dst_u, uint8* dst_v, } #endif // HAS_MIRRORROW_UV_SSSE3 -#ifdef HAS_ARGBMIRRORROW_SSSE3 -// Shuffle table for reversing the bytes. -static const uvec8 kARGBShuffleMirror = { - 12u, 13u, 14u, 15u, 8u, 9u, 10u, 11u, 4u, 5u, 6u, 7u, 0u, 1u, 2u, 3u -}; - -__declspec(naked) __declspec(align(16)) -void ARGBMirrorRow_SSSE3(const uint8* src, uint8* dst, int width) { +#ifdef HAS_ARGBMIRRORROW_SSE2 +__declspec(naked) +void ARGBMirrorRow_SSE2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src mov edx, [esp + 8] // dst mov ecx, [esp + 12] // width lea eax, [eax - 16 + ecx * 4] // last 4 pixels. - movdqa xmm5, kARGBShuffleMirror - align 4 convertloop: - movdqa xmm0, [eax] + movdqu xmm0, [eax] lea eax, [eax - 16] - pshufb xmm0, xmm5 - sub ecx, 4 - movdqa [edx], xmm0 + pshufd xmm0, xmm0, 0x1b + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop ret } } -#endif // HAS_ARGBMIRRORROW_SSSE3 +#endif // HAS_ARGBMIRRORROW_SSE2 #ifdef HAS_ARGBMIRRORROW_AVX2 // Shuffle table for reversing the bytes. @@ -3430,21 +3217,19 @@ static const ulvec32 kARGBShuffleMirror_AVX2 = { 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u }; -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBMirrorRow_AVX2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src mov edx, [esp + 8] // dst mov ecx, [esp + 12] // width - lea eax, [eax - 32] - vmovdqa ymm5, kARGBShuffleMirror_AVX2 + vmovdqu ymm5, ymmword ptr kARGBShuffleMirror_AVX2 - align 4 convertloop: - vpermd ymm0, ymm5, [eax + ecx * 4] // permute dword order - sub ecx, 8 + vpermd ymm0, ymm5, [eax - 32 + ecx * 4] // permute dword order vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 8 jg convertloop vzeroupper ret @@ -3453,56 +3238,19 @@ void ARGBMirrorRow_AVX2(const uint8* src, uint8* dst, int width) { #endif // HAS_ARGBMIRRORROW_AVX2 #ifdef HAS_SPLITUVROW_SSE2 -__declspec(naked) __declspec(align(16)) -void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) { +__declspec(naked) +void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_uv mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 sub edi, edx - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - movdqa xmm2, xmm0 - movdqa xmm3, xmm1 - pand xmm0, xmm5 // even bytes - pand xmm1, xmm5 - packuswb xmm0, xmm1 - psrlw xmm2, 8 // odd bytes - psrlw xmm3, 8 - packuswb xmm2, xmm3 - movdqa [edx], xmm0 - movdqa [edx + edi], xmm2 - lea edx, [edx + 16] - sub ecx, 16 - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void SplitUVRow_Unaligned_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, - int pix) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_uv - mov edx, [esp + 4 + 8] // dst_u - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - sub edi, edx - - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -3525,22 +3273,23 @@ void SplitUVRow_Unaligned_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, ret } } + #endif // HAS_SPLITUVROW_SSE2 #ifdef HAS_SPLITUVROW_AVX2 -__declspec(naked) __declspec(align(16)) -void SplitUVRow_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) { +__declspec(naked) +void SplitUVRow_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, + int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_uv mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 sub edi, edx - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -3567,7 +3316,7 @@ void SplitUVRow_AVX2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) { #endif // HAS_SPLITUVROW_AVX2 #ifdef HAS_MERGEUVROW_SSE2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void MergeUVRow_SSE2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) { __asm { @@ -3578,37 +3327,6 @@ void MergeUVRow_SSE2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, mov ecx, [esp + 4 + 16] // width sub edx, eax - align 4 - convertloop: - movdqa xmm0, [eax] // read 16 U's - movdqa xmm1, [eax + edx] // and 16 V's - lea eax, [eax + 16] - movdqa xmm2, xmm0 - punpcklbw xmm0, xmm1 // first 8 UV pairs - punpckhbw xmm2, xmm1 // next 8 UV pairs - movdqa [edi], xmm0 - movdqa [edi + 16], xmm2 - lea edi, [edi + 32] - sub ecx, 16 - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void MergeUVRow_Unaligned_SSE2(const uint8* src_u, const uint8* src_v, - uint8* dst_uv, int width) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_u - mov edx, [esp + 4 + 8] // src_v - mov edi, [esp + 4 + 12] // dst_uv - mov ecx, [esp + 4 + 16] // width - sub edx, eax - - align 4 convertloop: movdqu xmm0, [eax] // read 16 U's movdqu xmm1, [eax + edx] // and 16 V's @@ -3629,7 +3347,7 @@ void MergeUVRow_Unaligned_SSE2(const uint8* src_u, const uint8* src_v, #endif // HAS_MERGEUVROW_SSE2 #ifdef HAS_MERGEUVROW_AVX2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void MergeUVRow_AVX2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, int width) { __asm { @@ -3640,17 +3358,16 @@ void MergeUVRow_AVX2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, mov ecx, [esp + 4 + 16] // width sub edx, eax - align 4 convertloop: vmovdqu ymm0, [eax] // read 32 U's vmovdqu ymm1, [eax + edx] // and 32 V's lea eax, [eax + 32] vpunpcklbw ymm2, ymm0, ymm1 // low 16 UV pairs. mutated qqword 0,2 vpunpckhbw ymm0, ymm0, ymm1 // high 16 UV pairs. mutated qqword 1,3 - vperm2i128 ymm1, ymm2, ymm0, 0x20 // low 128 of ymm2 and low 128 of ymm0 - vperm2i128 ymm2, ymm2, ymm0, 0x31 // high 128 of ymm2 and high 128 of ymm0 - vmovdqu [edi], ymm1 - vmovdqu [edi + 32], ymm2 + vextractf128 [edi], ymm2, 0 // bytes 0..15 + vextractf128 [edi + 16], ymm0, 0 // bytes 16..31 + vextractf128 [edi + 32], ymm2, 1 // bytes 32..47 + vextractf128 [edi + 48], ymm0, 1 // bytes 47..63 lea edi, [edi + 64] sub ecx, 32 jg convertloop @@ -3664,15 +3381,18 @@ void MergeUVRow_AVX2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, #ifdef HAS_COPYROW_SSE2 // CopyRow copys 'count' bytes using a 16 byte load/store, 32 bytes at time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void CopyRow_SSE2(const uint8* src, uint8* dst, int count) { __asm { mov eax, [esp + 4] // src mov edx, [esp + 8] // dst mov ecx, [esp + 12] // count + test eax, 15 + jne convertloopu + test edx, 15 + jne convertloopu - align 4 - convertloop: + convertloopa: movdqa xmm0, [eax] movdqa xmm1, [eax + 16] lea eax, [eax + 32] @@ -3680,14 +3400,50 @@ void CopyRow_SSE2(const uint8* src, uint8* dst, int count) { movdqa [edx + 16], xmm1 lea edx, [edx + 32] sub ecx, 32 - jg convertloop + jg convertloopa + ret + + convertloopu: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + lea eax, [eax + 32] + movdqu [edx], xmm0 + movdqu [edx + 16], xmm1 + lea edx, [edx + 32] + sub ecx, 32 + jg convertloopu ret } } #endif // HAS_COPYROW_SSE2 -// Unaligned Multiple of 1. -__declspec(naked) __declspec(align(16)) +#ifdef HAS_COPYROW_AVX +// CopyRow copys 'count' bytes using a 32 byte load/store, 64 bytes at time. +__declspec(naked) +void CopyRow_AVX(const uint8* src, uint8* dst, int count) { + __asm { + mov eax, [esp + 4] // src + mov edx, [esp + 8] // dst + mov ecx, [esp + 12] // count + + convertloop: + vmovdqu ymm0, [eax] + vmovdqu ymm1, [eax + 32] + lea eax, [eax + 64] + vmovdqu [edx], ymm0 + vmovdqu [edx + 32], ymm1 + lea edx, [edx + 64] + sub ecx, 64 + jg convertloop + + vzeroupper + ret + } +} +#endif // HAS_COPYROW_AVX + +// Multiple of 1. +__declspec(naked) void CopyRow_ERMS(const uint8* src, uint8* dst, int count) { __asm { mov eax, esi @@ -3702,27 +3458,9 @@ void CopyRow_ERMS(const uint8* src, uint8* dst, int count) { } } -#ifdef HAS_COPYROW_X86 -__declspec(naked) __declspec(align(16)) -void CopyRow_X86(const uint8* src, uint8* dst, int count) { - __asm { - mov eax, esi - mov edx, edi - mov esi, [esp + 4] // src - mov edi, [esp + 8] // dst - mov ecx, [esp + 12] // count - shr ecx, 2 - rep movsd - mov edi, edx - mov esi, eax - ret - } -} -#endif // HAS_COPYROW_X86 - #ifdef HAS_ARGBCOPYALPHAROW_SSE2 // width in pixels -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBCopyAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src @@ -3733,21 +3471,20 @@ void ARGBCopyAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { pcmpeqb xmm1, xmm1 // generate mask 0x00ffffff psrld xmm1, 8 - align 4 convertloop: - movdqa xmm2, [eax] - movdqa xmm3, [eax + 16] + movdqu xmm2, [eax] + movdqu xmm3, [eax + 16] lea eax, [eax + 32] - movdqa xmm4, [edx] - movdqa xmm5, [edx + 16] + movdqu xmm4, [edx] + movdqu xmm5, [edx + 16] pand xmm2, xmm0 pand xmm3, xmm0 pand xmm4, xmm1 pand xmm5, xmm1 por xmm2, xmm4 por xmm3, xmm5 - movdqa [edx], xmm2 - movdqa [edx + 16], xmm3 + movdqu [edx], xmm2 + movdqu [edx + 16], xmm3 lea edx, [edx + 32] sub ecx, 8 jg convertloop @@ -3759,7 +3496,7 @@ void ARGBCopyAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { #ifdef HAS_ARGBCOPYALPHAROW_AVX2 // width in pixels -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBCopyAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src @@ -3768,7 +3505,6 @@ void ARGBCopyAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { vpcmpeqb ymm0, ymm0, ymm0 vpsrld ymm0, ymm0, 8 // generate mask 0x00ffffff - align 4 convertloop: vmovdqu ymm1, [eax] vmovdqu ymm2, [eax + 32] @@ -3789,7 +3525,7 @@ void ARGBCopyAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { #ifdef HAS_ARGBCOPYYTOALPHAROW_SSE2 // width in pixels -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBCopyYToAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src @@ -3800,23 +3536,22 @@ void ARGBCopyYToAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { pcmpeqb xmm1, xmm1 // generate mask 0x00ffffff psrld xmm1, 8 - align 4 convertloop: movq xmm2, qword ptr [eax] // 8 Y's lea eax, [eax + 8] punpcklbw xmm2, xmm2 punpckhwd xmm3, xmm2 punpcklwd xmm2, xmm2 - movdqa xmm4, [edx] - movdqa xmm5, [edx + 16] + movdqu xmm4, [edx] + movdqu xmm5, [edx + 16] pand xmm2, xmm0 pand xmm3, xmm0 pand xmm4, xmm1 pand xmm5, xmm1 por xmm2, xmm4 por xmm3, xmm5 - movdqa [edx], xmm2 - movdqa [edx + 16], xmm3 + movdqu [edx], xmm2 + movdqu [edx + 16], xmm3 lea edx, [edx + 32] sub ecx, 8 jg convertloop @@ -3828,7 +3563,7 @@ void ARGBCopyYToAlphaRow_SSE2(const uint8* src, uint8* dst, int width) { #ifdef HAS_ARGBCOPYYTOALPHAROW_AVX2 // width in pixels -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBCopyYToAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { __asm { mov eax, [esp + 4] // src @@ -3837,7 +3572,6 @@ void ARGBCopyYToAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { vpcmpeqb ymm0, ymm0, ymm0 vpsrld ymm0, ymm0, 8 // generate mask 0x00ffffff - align 4 convertloop: vpmovzxbd ymm1, qword ptr [eax] vpmovzxbd ymm2, qword ptr [eax + 8] @@ -3859,13 +3593,16 @@ void ARGBCopyYToAlphaRow_AVX2(const uint8* src, uint8* dst, int width) { #endif // HAS_ARGBCOPYYTOALPHAROW_AVX2 #ifdef HAS_SETROW_X86 -// SetRow8 writes 'count' bytes using a 32 bit value repeated. -__declspec(naked) __declspec(align(16)) -void SetRow_X86(uint8* dst, uint32 v32, int count) { +// Write 'count' bytes using an 8 bit value repeated. +// Count should be multiple of 4. +__declspec(naked) +void SetRow_X86(uint8* dst, uint8 v8, int count) { __asm { + movzx eax, byte ptr [esp + 8] // v8 + mov edx, 0x01010101 // Duplicate byte to all bytes. + mul edx // overwrites edx with upper part of result. mov edx, edi mov edi, [esp + 4] // dst - mov eax, [esp + 8] // v32 mov ecx, [esp + 12] // count shr ecx, 2 rep stosd @@ -3874,50 +3611,45 @@ void SetRow_X86(uint8* dst, uint32 v32, int count) { } } -// SetRow32 writes 'count' words using a 32 bit value repeated. -__declspec(naked) __declspec(align(16)) -void ARGBSetRows_X86(uint8* dst, uint32 v32, int width, - int dst_stride, int height) { +// Write 'count' bytes using an 8 bit value repeated. +__declspec(naked) +void SetRow_ERMS(uint8* dst, uint8 v8, int count) { __asm { - push esi - push edi - push ebp - mov edi, [esp + 12 + 4] // dst - mov eax, [esp + 12 + 8] // v32 - mov ebp, [esp + 12 + 12] // width - mov edx, [esp + 12 + 16] // dst_stride - mov esi, [esp + 12 + 20] // height - lea ecx, [ebp * 4] - sub edx, ecx // stride - width * 4 + mov edx, edi + mov edi, [esp + 4] // dst + mov eax, [esp + 8] // v8 + mov ecx, [esp + 12] // count + rep stosb + mov edi, edx + ret + } +} - align 4 - convertloop: - mov ecx, ebp +// Write 'count' 32 bit values. +__declspec(naked) +void ARGBSetRow_X86(uint8* dst_argb, uint32 v32, int count) { + __asm { + mov edx, edi + mov edi, [esp + 4] // dst + mov eax, [esp + 8] // v32 + mov ecx, [esp + 12] // count rep stosd - add edi, edx - sub esi, 1 - jg convertloop - - pop ebp - pop edi - pop esi + mov edi, edx ret } } #endif // HAS_SETROW_X86 #ifdef HAS_YUY2TOYROW_AVX2 -__declspec(naked) __declspec(align(16)) -void YUY2ToYRow_AVX2(const uint8* src_yuy2, - uint8* dst_y, int pix) { +__declspec(naked) +void YUY2ToYRow_AVX2(const uint8* src_yuy2, uint8* dst_y, int width) { __asm { mov eax, [esp + 4] // src_yuy2 mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -3926,18 +3658,18 @@ void YUY2ToYRow_AVX2(const uint8* src_yuy2, vpand ymm1, ymm1, ymm5 vpackuswb ymm0, ymm0, ymm1 // mutates. vpermq ymm0, ymm0, 0xd8 - sub ecx, 32 vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 32 jg convertloop vzeroupper ret } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void YUY2ToUVRow_AVX2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push esi push edi @@ -3945,12 +3677,11 @@ void YUY2ToUVRow_AVX2(const uint8* src_yuy2, int stride_yuy2, mov esi, [esp + 8 + 8] // stride_yuy2 mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix + mov ecx, [esp + 8 + 20] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 sub edi, edx - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -3980,20 +3711,19 @@ void YUY2ToUVRow_AVX2(const uint8* src_yuy2, int stride_yuy2, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void YUY2ToUV422Row_AVX2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_yuy2 mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 sub edi, edx - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -4020,15 +3750,14 @@ void YUY2ToUV422Row_AVX2(const uint8* src_yuy2, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void UYVYToYRow_AVX2(const uint8* src_uyvy, - uint8* dst_y, int pix) { + uint8* dst_y, int width) { __asm { mov eax, [esp + 4] // src_uyvy mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -4037,18 +3766,18 @@ void UYVYToYRow_AVX2(const uint8* src_uyvy, vpsrlw ymm1, ymm1, 8 vpackuswb ymm0, ymm0, ymm1 // mutates. vpermq ymm0, ymm0, 0xd8 - sub ecx, 32 vmovdqu [edx], ymm0 lea edx, [edx + 32] + sub ecx, 32 jg convertloop - ret vzeroupper + ret } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void UYVYToUVRow_AVX2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push esi push edi @@ -4056,12 +3785,11 @@ void UYVYToUVRow_AVX2(const uint8* src_uyvy, int stride_uyvy, mov esi, [esp + 8 + 8] // stride_yuy2 mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix + mov ecx, [esp + 8 + 20] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 sub edi, edx - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -4091,20 +3819,19 @@ void UYVYToUVRow_AVX2(const uint8* src_uyvy, int stride_uyvy, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void UYVYToUV422Row_AVX2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_yuy2 mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff00ff vpsrlw ymm5, ymm5, 8 sub edi, edx - align 4 convertloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] @@ -4133,35 +3860,34 @@ void UYVYToUV422Row_AVX2(const uint8* src_uyvy, #endif // HAS_YUY2TOYROW_AVX2 #ifdef HAS_YUY2TOYROW_SSE2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void YUY2ToYRow_SSE2(const uint8* src_yuy2, - uint8* dst_y, int pix) { + uint8* dst_y, int width) { __asm { mov eax, [esp + 4] // src_yuy2 mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 - align 4 convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] lea eax, [eax + 32] pand xmm0, xmm5 // even bytes are Y pand xmm1, xmm5 packuswb xmm0, xmm1 - sub ecx, 16 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop ret } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void YUY2ToUVRow_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push esi push edi @@ -4169,17 +3895,16 @@ void YUY2ToUVRow_SSE2(const uint8* src_yuy2, int stride_yuy2, mov esi, [esp + 8 + 8] // stride_yuy2 mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix + mov ecx, [esp + 8 + 20] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 sub edi, edx - align 4 convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + esi] - movdqa xmm3, [eax + esi + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + esi] + movdqu xmm3, [eax + esi + 16] lea eax, [eax + 32] pavgb xmm0, xmm2 pavgb xmm1, xmm3 @@ -4203,127 +3928,19 @@ void YUY2ToUVRow_SSE2(const uint8* src_yuy2, int stride_yuy2, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void YUY2ToUV422Row_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { + uint8* dst_u, uint8* dst_v, int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_yuy2 mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 sub edi, edx - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - psrlw xmm0, 8 // YUYV -> UVUV - psrlw xmm1, 8 - packuswb xmm0, xmm1 - movdqa xmm1, xmm0 - pand xmm0, xmm5 // U - packuswb xmm0, xmm0 - psrlw xmm1, 8 // V - packuswb xmm1, xmm1 - movq qword ptr [edx], xmm0 - movq qword ptr [edx + edi], xmm1 - lea edx, [edx + 8] - sub ecx, 16 - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void YUY2ToYRow_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] // src_yuy2 - mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - - align 4 - convertloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - lea eax, [eax + 32] - pand xmm0, xmm5 // even bytes are Y - pand xmm1, xmm5 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void YUY2ToUVRow_Unaligned_SSE2(const uint8* src_yuy2, int stride_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_yuy2 - mov esi, [esp + 8 + 8] // stride_yuy2 - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - sub edi, edx - - align 4 - convertloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + esi] - movdqu xmm3, [eax + esi + 16] - lea eax, [eax + 32] - pavgb xmm0, xmm2 - pavgb xmm1, xmm3 - psrlw xmm0, 8 // YUYV -> UVUV - psrlw xmm1, 8 - packuswb xmm0, xmm1 - movdqa xmm1, xmm0 - pand xmm0, xmm5 // U - packuswb xmm0, xmm0 - psrlw xmm1, 8 // V - packuswb xmm1, xmm1 - movq qword ptr [edx], xmm0 - movq qword ptr [edx + edi], xmm1 - lea edx, [edx + 8] - sub ecx, 16 - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void YUY2ToUV422Row_Unaligned_SSE2(const uint8* src_yuy2, - uint8* dst_u, uint8* dst_v, int pix) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_yuy2 - mov edx, [esp + 4 + 8] // dst_u - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - sub edi, edx - - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -4347,120 +3964,14 @@ void YUY2ToUV422Row_Unaligned_SSE2(const uint8* src_yuy2, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void UYVYToYRow_SSE2(const uint8* src_uyvy, - uint8* dst_y, int pix) { + uint8* dst_y, int width) { __asm { mov eax, [esp + 4] // src_uyvy mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix + mov ecx, [esp + 12] // width - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - psrlw xmm0, 8 // odd bytes are Y - psrlw xmm1, 8 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void UYVYToUVRow_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - __asm { - push esi - push edi - mov eax, [esp + 8 + 4] // src_yuy2 - mov esi, [esp + 8 + 8] // stride_yuy2 - mov edx, [esp + 8 + 12] // dst_u - mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - sub edi, edx - - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + esi] - movdqa xmm3, [eax + esi + 16] - lea eax, [eax + 32] - pavgb xmm0, xmm2 - pavgb xmm1, xmm3 - pand xmm0, xmm5 // UYVY -> UVUV - pand xmm1, xmm5 - packuswb xmm0, xmm1 - movdqa xmm1, xmm0 - pand xmm0, xmm5 // U - packuswb xmm0, xmm0 - psrlw xmm1, 8 // V - packuswb xmm1, xmm1 - movq qword ptr [edx], xmm0 - movq qword ptr [edx + edi], xmm1 - lea edx, [edx + 8] - sub ecx, 16 - jg convertloop - - pop edi - pop esi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void UYVYToUV422Row_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_yuy2 - mov edx, [esp + 4 + 8] // dst_u - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - sub edi, edx - - align 4 - convertloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - pand xmm0, xmm5 // UYVY -> UVUV - pand xmm1, xmm5 - packuswb xmm0, xmm1 - movdqa xmm1, xmm0 - pand xmm0, xmm5 // U - packuswb xmm0, xmm0 - psrlw xmm1, 8 // V - packuswb xmm1, xmm1 - movq qword ptr [edx], xmm0 - movq qword ptr [edx + edi], xmm1 - lea edx, [edx + 8] - sub ecx, 16 - jg convertloop - - pop edi - ret - } -} - -__declspec(naked) __declspec(align(16)) -void UYVYToYRow_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_y, int pix) { - __asm { - mov eax, [esp + 4] // src_uyvy - mov edx, [esp + 8] // dst_y - mov ecx, [esp + 12] // pix - - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -4468,17 +3979,17 @@ void UYVYToYRow_Unaligned_SSE2(const uint8* src_uyvy, psrlw xmm0, 8 // odd bytes are Y psrlw xmm1, 8 packuswb xmm0, xmm1 - sub ecx, 16 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop ret } } -__declspec(naked) __declspec(align(16)) -void UYVYToUVRow_Unaligned_SSE2(const uint8* src_uyvy, int stride_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { +__declspec(naked) +void UYVYToUVRow_SSE2(const uint8* src_uyvy, int stride_uyvy, + uint8* dst_u, uint8* dst_v, int width) { __asm { push esi push edi @@ -4486,12 +3997,11 @@ void UYVYToUVRow_Unaligned_SSE2(const uint8* src_uyvy, int stride_uyvy, mov esi, [esp + 8 + 8] // stride_yuy2 mov edx, [esp + 8 + 12] // dst_u mov edi, [esp + 8 + 16] // dst_v - mov ecx, [esp + 8 + 20] // pix + mov ecx, [esp + 8 + 20] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 sub edi, edx - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -4520,20 +4030,19 @@ void UYVYToUVRow_Unaligned_SSE2(const uint8* src_uyvy, int stride_uyvy, } } -__declspec(naked) __declspec(align(16)) -void UYVYToUV422Row_Unaligned_SSE2(const uint8* src_uyvy, - uint8* dst_u, uint8* dst_v, int pix) { +__declspec(naked) +void UYVYToUV422Row_SSE2(const uint8* src_uyvy, + uint8* dst_u, uint8* dst_v, int width) { __asm { push edi mov eax, [esp + 4 + 4] // src_yuy2 mov edx, [esp + 4 + 8] // dst_u mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix + mov ecx, [esp + 4 + 16] // width pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff psrlw xmm5, 8 sub edi, edx - align 4 convertloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] @@ -4558,127 +4067,122 @@ void UYVYToUV422Row_Unaligned_SSE2(const uint8* src_uyvy, } #endif // HAS_YUY2TOYROW_SSE2 -#ifdef HAS_ARGBBLENDROW_SSE2 +#ifdef HAS_BLENDPLANEROW_SSSE3 // Blend 8 pixels at a time. -__declspec(naked) __declspec(align(16)) -void ARGBBlendRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, - uint8* dst_argb, int width) { +// unsigned version of math +// =((A2*C2)+(B2*(255-C2))+255)/256 +// signed version of math +// =(((A2-128)*C2)+((B2-128)*(255-C2))+32768+127)/256 +__declspec(naked) +void BlendPlaneRow_SSSE3(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width) { __asm { push esi - mov eax, [esp + 4 + 4] // src_argb0 - mov esi, [esp + 4 + 8] // src_argb1 - mov edx, [esp + 4 + 12] // dst_argb - mov ecx, [esp + 4 + 16] // width - pcmpeqb xmm7, xmm7 // generate constant 1 - psrlw xmm7, 15 - pcmpeqb xmm6, xmm6 // generate mask 0x00ff00ff - psrlw xmm6, 8 + push edi pcmpeqb xmm5, xmm5 // generate mask 0xff00ff00 psllw xmm5, 8 - pcmpeqb xmm4, xmm4 // generate mask 0xff000000 - pslld xmm4, 24 + mov eax, 0x80808080 // 128 for biasing image to signed. + movd xmm6, eax + pshufd xmm6, xmm6, 0x00 - sub ecx, 1 - je convertloop1 // only 1 pixel? - jl convertloop1b + mov eax, 0x807f807f // 32768 + 127 for unbias and round. + movd xmm7, eax + pshufd xmm7, xmm7, 0x00 + mov eax, [esp + 8 + 4] // src0 + mov edx, [esp + 8 + 8] // src1 + mov esi, [esp + 8 + 12] // alpha + mov edi, [esp + 8 + 16] // dst + mov ecx, [esp + 8 + 20] // width + sub eax, esi + sub edx, esi + sub edi, esi - // 1 pixel loop until destination pointer is aligned. - alignloop1: - test edx, 15 // aligned? - je alignloop1b - movd xmm3, [eax] - lea eax, [eax + 4] - movdqa xmm0, xmm3 // src argb - pxor xmm3, xmm4 // ~alpha - movd xmm2, [esi] // _r_b - psrlw xmm3, 8 // alpha - pshufhw xmm3, xmm3, 0F5h // 8 alpha words - pshuflw xmm3, xmm3, 0F5h - pand xmm2, xmm6 // _r_b - paddw xmm3, xmm7 // 256 - alpha - pmullw xmm2, xmm3 // _r_b * alpha - movd xmm1, [esi] // _a_g - lea esi, [esi + 4] - psrlw xmm1, 8 // _a_g - por xmm0, xmm4 // set alpha to 255 - pmullw xmm1, xmm3 // _a_g * alpha - psrlw xmm2, 8 // _r_b convert to 8 bits again - paddusb xmm0, xmm2 // + src argb - pand xmm1, xmm5 // a_g_ convert to 8 bits again - paddusb xmm0, xmm1 // + src argb - sub ecx, 1 - movd [edx], xmm0 - lea edx, [edx + 4] - jge alignloop1 + // 8 pixel loop. + convertloop8: + movq xmm0, qword ptr [esi] // alpha + punpcklbw xmm0, xmm0 + pxor xmm0, xmm5 // a, 255-a + movq xmm1, qword ptr [eax + esi] // src0 + movq xmm2, qword ptr [edx + esi] // src1 + punpcklbw xmm1, xmm2 + psubb xmm1, xmm6 // bias src0/1 - 128 + pmaddubsw xmm0, xmm1 + paddw xmm0, xmm7 // unbias result - 32768 and round. + psrlw xmm0, 8 + packuswb xmm0, xmm0 + movq qword ptr [edi + esi], xmm0 + lea esi, [esi + 8] + sub ecx, 8 + jg convertloop8 - alignloop1b: - add ecx, 1 - 4 - jl convertloop4b - - // 4 pixel loop. - convertloop4: - movdqu xmm3, [eax] // src argb - lea eax, [eax + 16] - movdqa xmm0, xmm3 // src argb - pxor xmm3, xmm4 // ~alpha - movdqu xmm2, [esi] // _r_b - psrlw xmm3, 8 // alpha - pshufhw xmm3, xmm3, 0F5h // 8 alpha words - pshuflw xmm3, xmm3, 0F5h - pand xmm2, xmm6 // _r_b - paddw xmm3, xmm7 // 256 - alpha - pmullw xmm2, xmm3 // _r_b * alpha - movdqu xmm1, [esi] // _a_g - lea esi, [esi + 16] - psrlw xmm1, 8 // _a_g - por xmm0, xmm4 // set alpha to 255 - pmullw xmm1, xmm3 // _a_g * alpha - psrlw xmm2, 8 // _r_b convert to 8 bits again - paddusb xmm0, xmm2 // + src argb - pand xmm1, xmm5 // a_g_ convert to 8 bits again - paddusb xmm0, xmm1 // + src argb - sub ecx, 4 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jge convertloop4 - - convertloop4b: - add ecx, 4 - 1 - jl convertloop1b - - // 1 pixel loop. - convertloop1: - movd xmm3, [eax] // src argb - lea eax, [eax + 4] - movdqa xmm0, xmm3 // src argb - pxor xmm3, xmm4 // ~alpha - movd xmm2, [esi] // _r_b - psrlw xmm3, 8 // alpha - pshufhw xmm3, xmm3, 0F5h // 8 alpha words - pshuflw xmm3, xmm3, 0F5h - pand xmm2, xmm6 // _r_b - paddw xmm3, xmm7 // 256 - alpha - pmullw xmm2, xmm3 // _r_b * alpha - movd xmm1, [esi] // _a_g - lea esi, [esi + 4] - psrlw xmm1, 8 // _a_g - por xmm0, xmm4 // set alpha to 255 - pmullw xmm1, xmm3 // _a_g * alpha - psrlw xmm2, 8 // _r_b convert to 8 bits again - paddusb xmm0, xmm2 // + src argb - pand xmm1, xmm5 // a_g_ convert to 8 bits again - paddusb xmm0, xmm1 // + src argb - sub ecx, 1 - movd [edx], xmm0 - lea edx, [edx + 4] - jge convertloop1 - - convertloop1b: + pop edi pop esi ret } } -#endif // HAS_ARGBBLENDROW_SSE2 +#endif // HAS_BLENDPLANEROW_SSSE3 + +#ifdef HAS_BLENDPLANEROW_AVX2 +// Blend 32 pixels at a time. +// unsigned version of math +// =((A2*C2)+(B2*(255-C2))+255)/256 +// signed version of math +// =(((A2-128)*C2)+((B2-128)*(255-C2))+32768+127)/256 +__declspec(naked) +void BlendPlaneRow_AVX2(const uint8* src0, const uint8* src1, + const uint8* alpha, uint8* dst, int width) { + __asm { + push esi + push edi + vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0xff00ff00 + vpsllw ymm5, ymm5, 8 + mov eax, 0x80808080 // 128 for biasing image to signed. + vmovd xmm6, eax + vbroadcastss ymm6, xmm6 + mov eax, 0x807f807f // 32768 + 127 for unbias and round. + vmovd xmm7, eax + vbroadcastss ymm7, xmm7 + mov eax, [esp + 8 + 4] // src0 + mov edx, [esp + 8 + 8] // src1 + mov esi, [esp + 8 + 12] // alpha + mov edi, [esp + 8 + 16] // dst + mov ecx, [esp + 8 + 20] // width + sub eax, esi + sub edx, esi + sub edi, esi + + // 32 pixel loop. + convertloop32: + vmovdqu ymm0, [esi] // alpha + vpunpckhbw ymm3, ymm0, ymm0 // 8..15, 24..31 + vpunpcklbw ymm0, ymm0, ymm0 // 0..7, 16..23 + vpxor ymm3, ymm3, ymm5 // a, 255-a + vpxor ymm0, ymm0, ymm5 // a, 255-a + vmovdqu ymm1, [eax + esi] // src0 + vmovdqu ymm2, [edx + esi] // src1 + vpunpckhbw ymm4, ymm1, ymm2 + vpunpcklbw ymm1, ymm1, ymm2 + vpsubb ymm4, ymm4, ymm6 // bias src0/1 - 128 + vpsubb ymm1, ymm1, ymm6 // bias src0/1 - 128 + vpmaddubsw ymm3, ymm3, ymm4 + vpmaddubsw ymm0, ymm0, ymm1 + vpaddw ymm3, ymm3, ymm7 // unbias result - 32768 and round. + vpaddw ymm0, ymm0, ymm7 // unbias result - 32768 and round. + vpsrlw ymm3, ymm3, 8 + vpsrlw ymm0, ymm0, 8 + vpackuswb ymm0, ymm0, ymm3 + vmovdqu [edi + esi], ymm0 + lea esi, [esi + 32] + sub ecx, 32 + jg convertloop32 + + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_BLENDPLANEROW_AVX2 #ifdef HAS_ARGBBLENDROW_SSSE3 // Shuffle table for isolating alpha. @@ -4686,15 +4190,9 @@ static const uvec8 kShuffleAlpha = { 3u, 0x80, 3u, 0x80, 7u, 0x80, 7u, 0x80, 11u, 0x80, 11u, 0x80, 15u, 0x80, 15u, 0x80 }; -// Same as SSE2, but replaces: -// psrlw xmm3, 8 // alpha -// pshufhw xmm3, xmm3, 0F5h // 8 alpha words -// pshuflw xmm3, xmm3, 0F5h -// with.. -// pshufb xmm3, kShuffleAlpha // alpha -// Blend 8 pixels at a time. -__declspec(naked) __declspec(align(16)) +// Blend 8 pixels at a time. +__declspec(naked) void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -4711,81 +4209,17 @@ void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, psllw xmm5, 8 pcmpeqb xmm4, xmm4 // generate mask 0xff000000 pslld xmm4, 24 - - sub ecx, 1 - je convertloop1 // only 1 pixel? - jl convertloop1b - - // 1 pixel loop until destination pointer is aligned. - alignloop1: - test edx, 15 // aligned? - je alignloop1b - movd xmm3, [eax] - lea eax, [eax + 4] - movdqa xmm0, xmm3 // src argb - pxor xmm3, xmm4 // ~alpha - movd xmm2, [esi] // _r_b - pshufb xmm3, kShuffleAlpha // alpha - pand xmm2, xmm6 // _r_b - paddw xmm3, xmm7 // 256 - alpha - pmullw xmm2, xmm3 // _r_b * alpha - movd xmm1, [esi] // _a_g - lea esi, [esi + 4] - psrlw xmm1, 8 // _a_g - por xmm0, xmm4 // set alpha to 255 - pmullw xmm1, xmm3 // _a_g * alpha - psrlw xmm2, 8 // _r_b convert to 8 bits again - paddusb xmm0, xmm2 // + src argb - pand xmm1, xmm5 // a_g_ convert to 8 bits again - paddusb xmm0, xmm1 // + src argb - sub ecx, 1 - movd [edx], xmm0 - lea edx, [edx + 4] - jge alignloop1 - - alignloop1b: - add ecx, 1 - 4 - jl convertloop4b - - test eax, 15 // unaligned? - jne convertuloop4 - test esi, 15 // unaligned? - jne convertuloop4 + sub ecx, 4 + jl convertloop4b // less than 4 pixels? // 4 pixel loop. convertloop4: - movdqa xmm3, [eax] // src argb - lea eax, [eax + 16] - movdqa xmm0, xmm3 // src argb - pxor xmm3, xmm4 // ~alpha - movdqa xmm2, [esi] // _r_b - pshufb xmm3, kShuffleAlpha // alpha - pand xmm2, xmm6 // _r_b - paddw xmm3, xmm7 // 256 - alpha - pmullw xmm2, xmm3 // _r_b * alpha - movdqa xmm1, [esi] // _a_g - lea esi, [esi + 16] - psrlw xmm1, 8 // _a_g - por xmm0, xmm4 // set alpha to 255 - pmullw xmm1, xmm3 // _a_g * alpha - psrlw xmm2, 8 // _r_b convert to 8 bits again - paddusb xmm0, xmm2 // + src argb - pand xmm1, xmm5 // a_g_ convert to 8 bits again - paddusb xmm0, xmm1 // + src argb - sub ecx, 4 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jge convertloop4 - jmp convertloop4b - - // 4 pixel unaligned loop. - convertuloop4: movdqu xmm3, [eax] // src argb lea eax, [eax + 16] movdqa xmm0, xmm3 // src argb pxor xmm3, xmm4 // ~alpha movdqu xmm2, [esi] // _r_b - pshufb xmm3, kShuffleAlpha // alpha + pshufb xmm3, xmmword ptr kShuffleAlpha // alpha pand xmm2, xmm6 // _r_b paddw xmm3, xmm7 // 256 - alpha pmullw xmm2, xmm3 // _r_b * alpha @@ -4798,10 +4232,10 @@ void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, paddusb xmm0, xmm2 // + src argb pand xmm1, xmm5 // a_g_ convert to 8 bits again paddusb xmm0, xmm1 // + src argb - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] - jge convertuloop4 + sub ecx, 4 + jge convertloop4 convertloop4b: add ecx, 4 - 1 @@ -4814,7 +4248,7 @@ void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, movdqa xmm0, xmm3 // src argb pxor xmm3, xmm4 // ~alpha movd xmm2, [esi] // _r_b - pshufb xmm3, kShuffleAlpha // alpha + pshufb xmm3, xmmword ptr kShuffleAlpha // alpha pand xmm2, xmm6 // _r_b paddw xmm3, xmm7 // 256 - alpha pmullw xmm2, xmm3 // _r_b * alpha @@ -4827,9 +4261,9 @@ void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, paddusb xmm0, xmm2 // + src argb pand xmm1, xmm5 // a_g_ convert to 8 bits again paddusb xmm0, xmm1 // + src argb - sub ecx, 1 movd [edx], xmm0 lea edx, [edx + 4] + sub ecx, 1 jge convertloop1 convertloop1b: @@ -4839,50 +4273,6 @@ void ARGBBlendRow_SSSE3(const uint8* src_argb0, const uint8* src_argb1, } #endif // HAS_ARGBBLENDROW_SSSE3 -#ifdef HAS_ARGBATTENUATEROW_SSE2 -// Attenuate 4 pixels at a time. -// Aligned to 16 bytes. -__declspec(naked) __declspec(align(16)) -void ARGBAttenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width) { - __asm { - mov eax, [esp + 4] // src_argb0 - mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // width - pcmpeqb xmm4, xmm4 // generate mask 0xff000000 - pslld xmm4, 24 - pcmpeqb xmm5, xmm5 // generate mask 0x00ffffff - psrld xmm5, 8 - - align 4 - convertloop: - movdqa xmm0, [eax] // read 4 pixels - punpcklbw xmm0, xmm0 // first 2 - pshufhw xmm2, xmm0, 0FFh // 8 alpha words - pshuflw xmm2, xmm2, 0FFh - pmulhuw xmm0, xmm2 // rgb * a - movdqa xmm1, [eax] // read 4 pixels - punpckhbw xmm1, xmm1 // next 2 pixels - pshufhw xmm2, xmm1, 0FFh // 8 alpha words - pshuflw xmm2, xmm2, 0FFh - pmulhuw xmm1, xmm2 // rgb * a - movdqa xmm2, [eax] // alphas - lea eax, [eax + 16] - psrlw xmm0, 8 - pand xmm2, xmm4 - psrlw xmm1, 8 - packuswb xmm0, xmm1 - pand xmm0, xmm5 // keep original alphas - por xmm0, xmm2 - sub ecx, 4 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg convertloop - - ret - } -} -#endif // HAS_ARGBATTENUATEROW_SSE2 - #ifdef HAS_ARGBATTENUATEROW_SSSE3 // Shuffle table duplicating alpha. static const uvec8 kShuffleAlpha0 = { @@ -4892,7 +4282,7 @@ static const uvec8 kShuffleAlpha1 = { 11u, 11u, 11u, 11u, 11u, 11u, 128u, 128u, 15u, 15u, 15u, 15u, 15u, 15u, 128u, 128u, }; -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] // src_argb0 @@ -4900,10 +4290,9 @@ void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { mov ecx, [esp + 12] // width pcmpeqb xmm3, xmm3 // generate mask 0xff000000 pslld xmm3, 24 - movdqa xmm4, kShuffleAlpha0 - movdqa xmm5, kShuffleAlpha1 + movdqa xmm4, xmmword ptr kShuffleAlpha0 + movdqa xmm5, xmmword ptr kShuffleAlpha1 - align 4 convertloop: movdqu xmm0, [eax] // read 4 pixels pshufb xmm0, xmm4 // isolate first 2 alphas @@ -4922,9 +4311,9 @@ void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { psrlw xmm1, 8 packuswb xmm0, xmm1 por xmm0, xmm2 // copy original alpha - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop ret @@ -4934,24 +4323,20 @@ void ARGBAttenuateRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { #ifdef HAS_ARGBATTENUATEROW_AVX2 // Shuffle table duplicating alpha. -static const ulvec8 kShuffleAlpha_AVX2 = { - 6u, 7u, 6u, 7u, 6u, 7u, 128u, 128u, - 14u, 15u, 14u, 15u, 14u, 15u, 128u, 128u, - 6u, 7u, 6u, 7u, 6u, 7u, 128u, 128u, - 14u, 15u, 14u, 15u, 14u, 15u, 128u, 128u, +static const uvec8 kShuffleAlpha_AVX2 = { + 6u, 7u, 6u, 7u, 6u, 7u, 128u, 128u, 14u, 15u, 14u, 15u, 14u, 15u, 128u, 128u }; -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBAttenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] // src_argb0 mov edx, [esp + 8] // dst_argb mov ecx, [esp + 12] // width sub edx, eax - vmovdqa ymm4, kShuffleAlpha_AVX2 + vbroadcastf128 ymm4, xmmword ptr kShuffleAlpha_AVX2 vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0xff000000 vpslld ymm5, ymm5, 24 - align 4 convertloop: vmovdqu ymm6, [eax] // read 8 pixels. vpunpcklbw ymm0, ymm6, ymm6 // low 4 pixels. mutated. @@ -4965,9 +4350,9 @@ void ARGBAttenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width) { vpsrlw ymm1, ymm1, 8 vpackuswb ymm0, ymm0, ymm1 // unmutated. vpor ymm0, ymm0, ymm6 // copy original alpha - sub ecx, 8 vmovdqu [eax + edx], ymm0 lea eax, [eax + 32] + sub ecx, 8 jg convertloop vzeroupper @@ -4978,25 +4363,25 @@ void ARGBAttenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width) { #ifdef HAS_ARGBUNATTENUATEROW_SSE2 // Unattenuate 4 pixels at a time. -// Aligned to 16 bytes. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBUnattenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width) { __asm { + push ebx push esi push edi - mov eax, [esp + 8 + 4] // src_argb0 - mov edx, [esp + 8 + 8] // dst_argb - mov ecx, [esp + 8 + 12] // width + mov eax, [esp + 12 + 4] // src_argb + mov edx, [esp + 12 + 8] // dst_argb + mov ecx, [esp + 12 + 12] // width + lea ebx, fixed_invtbl8 - align 4 convertloop: movdqu xmm0, [eax] // read 4 pixels movzx esi, byte ptr [eax + 3] // first alpha movzx edi, byte ptr [eax + 7] // second alpha punpcklbw xmm0, xmm0 // first 2 - movd xmm2, dword ptr fixed_invtbl8[esi * 4] - movd xmm3, dword ptr fixed_invtbl8[edi * 4] + movd xmm2, dword ptr [ebx + esi * 4] + movd xmm3, dword ptr [ebx + edi * 4] pshuflw xmm2, xmm2, 040h // first 4 inv_alpha words. 1, a, a, a pshuflw xmm3, xmm3, 040h // next 4 inv_alpha words movlhps xmm2, xmm3 @@ -5006,21 +4391,22 @@ void ARGBUnattenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, movzx esi, byte ptr [eax + 11] // third alpha movzx edi, byte ptr [eax + 15] // forth alpha punpckhbw xmm1, xmm1 // next 2 - movd xmm2, dword ptr fixed_invtbl8[esi * 4] - movd xmm3, dword ptr fixed_invtbl8[edi * 4] + movd xmm2, dword ptr [ebx + esi * 4] + movd xmm3, dword ptr [ebx + edi * 4] pshuflw xmm2, xmm2, 040h // first 4 inv_alpha words pshuflw xmm3, xmm3, 040h // next 4 inv_alpha words movlhps xmm2, xmm3 pmulhuw xmm1, xmm2 // rgb * a lea eax, [eax + 16] - packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop + pop edi pop esi + pop ebx ret } } @@ -5028,14 +4414,13 @@ void ARGBUnattenuateRow_SSE2(const uint8* src_argb, uint8* dst_argb, #ifdef HAS_ARGBUNATTENUATEROW_AVX2 // Shuffle table duplicating alpha. -static const ulvec8 kUnattenShuffleAlpha_AVX2 = { - 0u, 1u, 0u, 1u, 0u, 1u, 6u, 7u, 8u, 9u, 8u, 9u, 8u, 9u, 14u, 15, - 0u, 1u, 0u, 1u, 0u, 1u, 6u, 7u, 8u, 9u, 8u, 9u, 8u, 9u, 14u, 15, +static const uvec8 kUnattenShuffleAlpha_AVX2 = { + 0u, 1u, 0u, 1u, 0u, 1u, 6u, 7u, 8u, 9u, 8u, 9u, 8u, 9u, 14u, 15u }; // TODO(fbarchard): Enable USE_GATHER for future hardware if faster. // USE_GATHER is not on by default, due to being a slow instruction. #ifdef USE_GATHER -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width) { __asm { @@ -5043,9 +4428,8 @@ void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, mov edx, [esp + 8] // dst_argb mov ecx, [esp + 12] // width sub edx, eax - vmovdqa ymm4, kUnattenShuffleAlpha_AVX2 + vbroadcastf128 ymm4, xmmword ptr kUnattenShuffleAlpha_AVX2 - align 4 convertloop: vmovdqu ymm6, [eax] // read 8 pixels. vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0xffffffff for gather. @@ -5060,9 +4444,9 @@ void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, vpmulhuw ymm0, ymm0, ymm2 // rgb * ia vpmulhuw ymm1, ymm1, ymm3 // rgb * ia vpackuswb ymm0, ymm0, ymm1 // unmutated. - sub ecx, 8 vmovdqu [eax + edx], ymm0 lea eax, [eax + 32] + sub ecx, 8 jg convertloop vzeroupper @@ -5070,42 +4454,42 @@ void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, } } #else // USE_GATHER -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, int width) { __asm { - mov eax, [esp + 4] // src_argb0 - mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // width - sub edx, eax - vmovdqa ymm5, kUnattenShuffleAlpha_AVX2 - + push ebx push esi push edi + mov eax, [esp + 12 + 4] // src_argb + mov edx, [esp + 12 + 8] // dst_argb + mov ecx, [esp + 12 + 12] // width + sub edx, eax + lea ebx, fixed_invtbl8 + vbroadcastf128 ymm5, xmmword ptr kUnattenShuffleAlpha_AVX2 - align 4 convertloop: // replace VPGATHER movzx esi, byte ptr [eax + 3] // alpha0 movzx edi, byte ptr [eax + 7] // alpha1 - vmovd xmm0, dword ptr fixed_invtbl8[esi * 4] // [1,a0] - vmovd xmm1, dword ptr fixed_invtbl8[edi * 4] // [1,a1] + vmovd xmm0, dword ptr [ebx + esi * 4] // [1,a0] + vmovd xmm1, dword ptr [ebx + edi * 4] // [1,a1] movzx esi, byte ptr [eax + 11] // alpha2 movzx edi, byte ptr [eax + 15] // alpha3 vpunpckldq xmm6, xmm0, xmm1 // [1,a1,1,a0] - vmovd xmm2, dword ptr fixed_invtbl8[esi * 4] // [1,a2] - vmovd xmm3, dword ptr fixed_invtbl8[edi * 4] // [1,a3] + vmovd xmm2, dword ptr [ebx + esi * 4] // [1,a2] + vmovd xmm3, dword ptr [ebx + edi * 4] // [1,a3] movzx esi, byte ptr [eax + 19] // alpha4 movzx edi, byte ptr [eax + 23] // alpha5 vpunpckldq xmm7, xmm2, xmm3 // [1,a3,1,a2] - vmovd xmm0, dword ptr fixed_invtbl8[esi * 4] // [1,a4] - vmovd xmm1, dword ptr fixed_invtbl8[edi * 4] // [1,a5] + vmovd xmm0, dword ptr [ebx + esi * 4] // [1,a4] + vmovd xmm1, dword ptr [ebx + edi * 4] // [1,a5] movzx esi, byte ptr [eax + 27] // alpha6 movzx edi, byte ptr [eax + 31] // alpha7 vpunpckldq xmm0, xmm0, xmm1 // [1,a5,1,a4] - vmovd xmm2, dword ptr fixed_invtbl8[esi * 4] // [1,a6] - vmovd xmm3, dword ptr fixed_invtbl8[edi * 4] // [1,a7] + vmovd xmm2, dword ptr [ebx + esi * 4] // [1,a6] + vmovd xmm3, dword ptr [ebx + edi * 4] // [1,a7] vpunpckldq xmm2, xmm2, xmm3 // [1,a7,1,a6] vpunpcklqdq xmm3, xmm6, xmm7 // [1,a3,1,a2,1,a1,1,a0] vpunpcklqdq xmm0, xmm0, xmm2 // [1,a7,1,a6,1,a5,1,a4] @@ -5122,13 +4506,14 @@ void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, vpmulhuw ymm0, ymm0, ymm2 // rgb * ia vpmulhuw ymm1, ymm1, ymm3 // rgb * ia vpackuswb ymm0, ymm0, ymm1 // unmutated. - sub ecx, 8 vmovdqu [eax + edx], ymm0 lea eax, [eax + 32] + sub ecx, 8 jg convertloop pop edi pop esi + pop ebx vzeroupper ret } @@ -5138,27 +4523,26 @@ void ARGBUnattenuateRow_AVX2(const uint8* src_argb, uint8* dst_argb, #ifdef HAS_ARGBGRAYROW_SSSE3 // Convert 8 ARGB pixels (64 bytes) to 8 Gray ARGB pixels. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBGrayRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] /* src_argb */ mov edx, [esp + 8] /* dst_argb */ mov ecx, [esp + 12] /* width */ - movdqa xmm4, kARGBToYJ - movdqa xmm5, kAddYJ64 + movdqa xmm4, xmmword ptr kARGBToYJ + movdqa xmm5, xmmword ptr kAddYJ64 - align 4 convertloop: - movdqa xmm0, [eax] // G - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] // G + movdqu xmm1, [eax + 16] pmaddubsw xmm0, xmm4 pmaddubsw xmm1, xmm4 phaddw xmm0, xmm1 paddw xmm0, xmm5 // Add .5 for rounding. psrlw xmm0, 7 packuswb xmm0, xmm0 // 8 G bytes - movdqa xmm2, [eax] // A - movdqa xmm3, [eax + 16] + movdqu xmm2, [eax] // A + movdqu xmm3, [eax + 16] lea eax, [eax + 32] psrld xmm2, 24 psrld xmm3, 24 @@ -5170,10 +4554,10 @@ void ARGBGrayRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width) { movdqa xmm1, xmm0 punpcklwd xmm0, xmm3 // GGGA first 4 punpckhwd xmm1, xmm3 // GGGA next 4 - sub ecx, 8 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 + movdqu [edx], xmm0 + movdqu [edx + 16], xmm1 lea edx, [edx + 32] + sub ecx, 8 jg convertloop ret } @@ -5198,41 +4582,40 @@ static const vec8 kARGBToSepiaR = { }; // Convert 8 ARGB pixels (32 bytes) to 8 Sepia ARGB pixels. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBSepiaRow_SSSE3(uint8* dst_argb, int width) { __asm { mov eax, [esp + 4] /* dst_argb */ mov ecx, [esp + 8] /* width */ - movdqa xmm2, kARGBToSepiaB - movdqa xmm3, kARGBToSepiaG - movdqa xmm4, kARGBToSepiaR + movdqa xmm2, xmmword ptr kARGBToSepiaB + movdqa xmm3, xmmword ptr kARGBToSepiaG + movdqa xmm4, xmmword ptr kARGBToSepiaR - align 4 convertloop: - movdqa xmm0, [eax] // B - movdqa xmm6, [eax + 16] + movdqu xmm0, [eax] // B + movdqu xmm6, [eax + 16] pmaddubsw xmm0, xmm2 pmaddubsw xmm6, xmm2 phaddw xmm0, xmm6 psrlw xmm0, 7 packuswb xmm0, xmm0 // 8 B values - movdqa xmm5, [eax] // G - movdqa xmm1, [eax + 16] + movdqu xmm5, [eax] // G + movdqu xmm1, [eax + 16] pmaddubsw xmm5, xmm3 pmaddubsw xmm1, xmm3 phaddw xmm5, xmm1 psrlw xmm5, 7 packuswb xmm5, xmm5 // 8 G values punpcklbw xmm0, xmm5 // 8 BG values - movdqa xmm5, [eax] // R - movdqa xmm1, [eax + 16] + movdqu xmm5, [eax] // R + movdqu xmm1, [eax + 16] pmaddubsw xmm5, xmm4 pmaddubsw xmm1, xmm4 phaddw xmm5, xmm1 psrlw xmm5, 7 packuswb xmm5, xmm5 // 8 R values - movdqa xmm6, [eax] // A - movdqa xmm1, [eax + 16] + movdqu xmm6, [eax] // A + movdqu xmm1, [eax + 16] psrld xmm6, 24 psrld xmm1, 24 packuswb xmm6, xmm1 @@ -5241,10 +4624,10 @@ void ARGBSepiaRow_SSSE3(uint8* dst_argb, int width) { movdqa xmm1, xmm0 // Weave BG, RA together punpcklwd xmm0, xmm5 // BGRA first 4 punpckhwd xmm1, xmm5 // BGRA next 4 - sub ecx, 8 - movdqa [eax], xmm0 - movdqa [eax + 16], xmm1 + movdqu [eax], xmm0 + movdqu [eax + 16], xmm1 lea eax, [eax + 32] + sub ecx, 8 jg convertloop ret } @@ -5256,7 +4639,7 @@ void ARGBSepiaRow_SSSE3(uint8* dst_argb, int width) { // Same as Sepia except matrix is provided. // TODO(fbarchard): packuswbs only use half of the reg. To make RGBA, combine R // and B into a high and low, then G/A, unpackl/hbw and then unpckl/hwd. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, const int8* matrix_argb, int width) { __asm { @@ -5270,14 +4653,13 @@ void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, pshufd xmm5, xmm5, 0xff mov ecx, [esp + 16] /* width */ - align 4 convertloop: - movdqa xmm0, [eax] // B - movdqa xmm7, [eax + 16] + movdqu xmm0, [eax] // B + movdqu xmm7, [eax + 16] pmaddubsw xmm0, xmm2 pmaddubsw xmm7, xmm2 - movdqa xmm6, [eax] // G - movdqa xmm1, [eax + 16] + movdqu xmm6, [eax] // G + movdqu xmm1, [eax + 16] pmaddubsw xmm6, xmm3 pmaddubsw xmm1, xmm3 phaddsw xmm0, xmm7 // B @@ -5287,13 +4669,13 @@ void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, packuswb xmm0, xmm0 // 8 B values packuswb xmm6, xmm6 // 8 G values punpcklbw xmm0, xmm6 // 8 BG values - movdqa xmm1, [eax] // R - movdqa xmm7, [eax + 16] + movdqu xmm1, [eax] // R + movdqu xmm7, [eax + 16] pmaddubsw xmm1, xmm4 pmaddubsw xmm7, xmm4 phaddsw xmm1, xmm7 // R - movdqa xmm6, [eax] // A - movdqa xmm7, [eax + 16] + movdqu xmm6, [eax] // A + movdqu xmm7, [eax + 16] pmaddubsw xmm6, xmm5 pmaddubsw xmm7, xmm5 phaddsw xmm6, xmm7 // A @@ -5305,11 +4687,11 @@ void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, movdqa xmm6, xmm0 // Weave BG, RA together punpcklwd xmm0, xmm1 // BGRA first 4 punpckhwd xmm6, xmm1 // BGRA next 4 - sub ecx, 8 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm6 + movdqu [edx], xmm0 + movdqu [edx + 16], xmm6 lea eax, [eax + 32] lea edx, [edx + 32] + sub ecx, 8 jg convertloop ret } @@ -5318,8 +4700,7 @@ void ARGBColorMatrixRow_SSSE3(const uint8* src_argb, uint8* dst_argb, #ifdef HAS_ARGBQUANTIZEROW_SSE2 // Quantize 4 ARGB pixels (16 bytes). -// Aligned to 16 bytes. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBQuantizeRow_SSE2(uint8* dst_argb, int scale, int interval_size, int interval_offset, int width) { __asm { @@ -5338,25 +4719,24 @@ void ARGBQuantizeRow_SSE2(uint8* dst_argb, int scale, int interval_size, pcmpeqb xmm6, xmm6 // generate mask 0xff000000 pslld xmm6, 24 - align 4 convertloop: - movdqa xmm0, [eax] // read 4 pixels + movdqu xmm0, [eax] // read 4 pixels punpcklbw xmm0, xmm5 // first 2 pixels pmulhuw xmm0, xmm2 // pixel * scale >> 16 - movdqa xmm1, [eax] // read 4 pixels + movdqu xmm1, [eax] // read 4 pixels punpckhbw xmm1, xmm5 // next 2 pixels pmulhuw xmm1, xmm2 pmullw xmm0, xmm3 // * interval_size - movdqa xmm7, [eax] // read 4 pixels + movdqu xmm7, [eax] // read 4 pixels pmullw xmm1, xmm3 pand xmm7, xmm6 // mask alpha paddw xmm0, xmm4 // + interval_size / 2 paddw xmm1, xmm4 packuswb xmm0, xmm1 por xmm0, xmm7 - sub ecx, 4 - movdqa [eax], xmm0 + movdqu [eax], xmm0 lea eax, [eax + 16] + sub ecx, 4 jg convertloop ret } @@ -5365,8 +4745,7 @@ void ARGBQuantizeRow_SSE2(uint8* dst_argb, int scale, int interval_size, #ifdef HAS_ARGBSHADEROW_SSE2 // Shade 4 pixels at a time by specified value. -// Aligned to 16 bytes. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width, uint32 value) { __asm { @@ -5377,9 +4756,8 @@ void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width, punpcklbw xmm2, xmm2 punpcklqdq xmm2, xmm2 - align 4 convertloop: - movdqa xmm0, [eax] // read 4 pixels + movdqu xmm0, [eax] // read 4 pixels lea eax, [eax + 16] movdqa xmm1, xmm0 punpcklbw xmm0, xmm0 // first 2 @@ -5389,9 +4767,9 @@ void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width, psrlw xmm0, 8 psrlw xmm1, 8 packuswb xmm0, xmm1 - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop ret @@ -5401,7 +4779,7 @@ void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width, #ifdef HAS_ARGBMULTIPLYROW_SSE2 // Multiply 2 rows of ARGB pixels together, 4 pixels at a time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBMultiplyRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5412,7 +4790,6 @@ void ARGBMultiplyRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, mov ecx, [esp + 4 + 16] // width pxor xmm5, xmm5 // constant 0 - align 4 convertloop: movdqu xmm0, [eax] // read 4 pixels from src_argb0 movdqu xmm2, [esi] // read 4 pixels from src_argb1 @@ -5427,9 +4804,9 @@ void ARGBMultiplyRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, lea eax, [eax + 16] lea esi, [esi + 16] packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop pop esi @@ -5441,7 +4818,7 @@ void ARGBMultiplyRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, #ifdef HAS_ARGBADDROW_SSE2 // Add 2 rows of ARGB pixels together, 4 pixels at a time. // TODO(fbarchard): Port this to posix, neon and other math functions. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBAddRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5454,16 +4831,15 @@ void ARGBAddRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, sub ecx, 4 jl convertloop49 - align 4 convertloop4: movdqu xmm0, [eax] // read 4 pixels from src_argb0 lea eax, [eax + 16] movdqu xmm1, [esi] // read 4 pixels from src_argb1 lea esi, [esi + 16] paddusb xmm0, xmm1 // src_argb0 + src_argb1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jge convertloop4 convertloop49: @@ -5476,9 +4852,9 @@ void ARGBAddRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, movd xmm1, [esi] // read 1 pixels from src_argb1 lea esi, [esi + 4] paddusb xmm0, xmm1 // src_argb0 + src_argb1 - sub ecx, 1 movd [edx], xmm0 lea edx, [edx + 4] + sub ecx, 1 jge convertloop1 convertloop19: @@ -5490,7 +4866,7 @@ void ARGBAddRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, #ifdef HAS_ARGBSUBTRACTROW_SSE2 // Subtract 2 rows of ARGB pixels together, 4 pixels at a time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBSubtractRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5500,16 +4876,15 @@ void ARGBSubtractRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, mov edx, [esp + 4 + 12] // dst_argb mov ecx, [esp + 4 + 16] // width - align 4 convertloop: movdqu xmm0, [eax] // read 4 pixels from src_argb0 lea eax, [eax + 16] movdqu xmm1, [esi] // read 4 pixels from src_argb1 lea esi, [esi + 16] psubusb xmm0, xmm1 // src_argb0 - src_argb1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg convertloop pop esi @@ -5520,7 +4895,7 @@ void ARGBSubtractRow_SSE2(const uint8* src_argb0, const uint8* src_argb1, #ifdef HAS_ARGBMULTIPLYROW_AVX2 // Multiply 2 rows of ARGB pixels together, 8 pixels at a time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBMultiplyRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5531,7 +4906,6 @@ void ARGBMultiplyRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, mov ecx, [esp + 4 + 16] // width vpxor ymm5, ymm5, ymm5 // constant 0 - align 4 convertloop: vmovdqu ymm1, [eax] // read 8 pixels from src_argb0 lea eax, [eax + 32] @@ -5558,7 +4932,7 @@ void ARGBMultiplyRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, #ifdef HAS_ARGBADDROW_AVX2 // Add 2 rows of ARGB pixels together, 8 pixels at a time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBAddRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5568,7 +4942,6 @@ void ARGBAddRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, mov edx, [esp + 4 + 12] // dst_argb mov ecx, [esp + 4 + 16] // width - align 4 convertloop: vmovdqu ymm0, [eax] // read 8 pixels from src_argb0 lea eax, [eax + 32] @@ -5588,7 +4961,7 @@ void ARGBAddRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, #ifdef HAS_ARGBSUBTRACTROW_AVX2 // Subtract 2 rows of ARGB pixels together, 8 pixels at a time. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBSubtractRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, uint8* dst_argb, int width) { __asm { @@ -5598,7 +4971,6 @@ void ARGBSubtractRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, mov edx, [esp + 4 + 12] // dst_argb mov ecx, [esp + 4 + 16] // width - align 4 convertloop: vmovdqu ymm0, [eax] // read 8 pixels from src_argb0 lea eax, [eax + 32] @@ -5621,7 +4993,7 @@ void ARGBSubtractRow_AVX2(const uint8* src_argb0, const uint8* src_argb1, // -1 0 1 // -2 0 2 // -1 0 1 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void SobelXRow_SSE2(const uint8* src_y0, const uint8* src_y1, const uint8* src_y2, uint8* dst_sobelx, int width) { __asm { @@ -5637,7 +5009,6 @@ void SobelXRow_SSE2(const uint8* src_y0, const uint8* src_y1, sub edx, eax pxor xmm5, xmm5 // constant 0 - align 4 convertloop: movq xmm0, qword ptr [eax] // read 8 pixels from src_y0[0] movq xmm1, qword ptr [eax + 2] // read 8 pixels from src_y0[2] @@ -5661,9 +5032,9 @@ void SobelXRow_SSE2(const uint8* src_y0, const uint8* src_y1, psubw xmm1, xmm0 pmaxsw xmm0, xmm1 packuswb xmm0, xmm0 - sub ecx, 8 movq qword ptr [eax + edx], xmm0 lea eax, [eax + 8] + sub ecx, 8 jg convertloop pop edi @@ -5678,7 +5049,7 @@ void SobelXRow_SSE2(const uint8* src_y0, const uint8* src_y1, // -1 -2 -1 // 0 0 0 // 1 2 1 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void SobelYRow_SSE2(const uint8* src_y0, const uint8* src_y1, uint8* dst_sobely, int width) { __asm { @@ -5691,7 +5062,6 @@ void SobelYRow_SSE2(const uint8* src_y0, const uint8* src_y1, sub edx, eax pxor xmm5, xmm5 // constant 0 - align 4 convertloop: movq xmm0, qword ptr [eax] // read 8 pixels from src_y0[0] movq xmm1, qword ptr [eax + esi] // read 8 pixels from src_y1[0] @@ -5715,9 +5085,9 @@ void SobelYRow_SSE2(const uint8* src_y0, const uint8* src_y1, psubw xmm1, xmm0 pmaxsw xmm0, xmm1 packuswb xmm0, xmm0 - sub ecx, 8 movq qword ptr [eax + edx], xmm0 lea eax, [eax + 8] + sub ecx, 8 jg convertloop pop esi @@ -5732,7 +5102,7 @@ void SobelYRow_SSE2(const uint8* src_y0, const uint8* src_y1, // R = Sobel // G = Sobel // B = Sobel -__declspec(naked) __declspec(align(16)) +__declspec(naked) void SobelRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width) { __asm { @@ -5745,10 +5115,9 @@ void SobelRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, pcmpeqb xmm5, xmm5 // alpha 255 pslld xmm5, 24 // 0xff000000 - align 4 convertloop: - movdqa xmm0, [eax] // read 16 pixels src_sobelx - movdqa xmm1, [eax + esi] // read 16 pixels src_sobely + movdqu xmm0, [eax] // read 16 pixels src_sobelx + movdqu xmm1, [eax + esi] // read 16 pixels src_sobely lea eax, [eax + 16] paddusb xmm0, xmm1 // sobel = sobelx + sobely movdqa xmm2, xmm0 // GG @@ -5764,12 +5133,12 @@ void SobelRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, punpckhwd xmm0, xmm0 // Last 4 por xmm3, xmm5 // GGGA por xmm0, xmm5 - sub ecx, 16 - movdqa [edx], xmm1 - movdqa [edx + 16], xmm2 - movdqa [edx + 32], xmm3 - movdqa [edx + 48], xmm0 + movdqu [edx], xmm1 + movdqu [edx + 16], xmm2 + movdqu [edx + 32], xmm3 + movdqu [edx + 48], xmm0 lea edx, [edx + 64] + sub ecx, 16 jg convertloop pop esi @@ -5780,7 +5149,7 @@ void SobelRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, #ifdef HAS_SOBELTOPLANEROW_SSE2 // Adds Sobel X and Sobel Y and stores Sobel into a plane. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void SobelToPlaneRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_y, int width) { __asm { @@ -5791,15 +5160,14 @@ void SobelToPlaneRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, mov ecx, [esp + 4 + 16] // width sub esi, eax - align 4 convertloop: - movdqa xmm0, [eax] // read 16 pixels src_sobelx - movdqa xmm1, [eax + esi] // read 16 pixels src_sobely + movdqu xmm0, [eax] // read 16 pixels src_sobelx + movdqu xmm1, [eax + esi] // read 16 pixels src_sobely lea eax, [eax + 16] paddusb xmm0, xmm1 // sobel = sobelx + sobely - sub ecx, 16 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 16 jg convertloop pop esi @@ -5814,7 +5182,7 @@ void SobelToPlaneRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, // R = Sobel X // G = Sobel // B = Sobel Y -__declspec(naked) __declspec(align(16)) +__declspec(naked) void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, uint8* dst_argb, int width) { __asm { @@ -5826,10 +5194,9 @@ void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, sub esi, eax pcmpeqb xmm5, xmm5 // alpha 255 - align 4 convertloop: - movdqa xmm0, [eax] // read 16 pixels src_sobelx - movdqa xmm1, [eax + esi] // read 16 pixels src_sobely + movdqu xmm0, [eax] // read 16 pixels src_sobelx + movdqu xmm1, [eax + esi] // read 16 pixels src_sobely lea eax, [eax + 16] movdqa xmm2, xmm0 paddusb xmm2, xmm1 // sobel = sobelx + sobely @@ -5845,12 +5212,12 @@ void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, movdqa xmm7, xmm1 // YSXA punpcklwd xmm7, xmm0 // Next 4 punpckhwd xmm1, xmm0 // Last 4 - sub ecx, 16 - movdqa [edx], xmm6 - movdqa [edx + 16], xmm4 - movdqa [edx + 32], xmm7 - movdqa [edx + 48], xmm1 + movdqu [edx], xmm6 + movdqu [edx + 16], xmm4 + movdqu [edx + 32], xmm7 + movdqu [edx + 48], xmm1 lea edx, [edx + 64] + sub ecx, 16 jg convertloop pop esi @@ -5871,8 +5238,7 @@ void SobelXYRow_SSE2(const uint8* src_sobelx, const uint8* src_sobely, // area is the number of pixels in the area being averaged. // dst points to pixel to store result to. // count is number of averaged pixels to produce. -// Does 4 pixels at a time, requires CumulativeSum pointers to be 16 byte -// aligned. +// Does 4 pixels at a time. void CumulativeSumToAverageRow_SSE2(const int32* topleft, const int32* botleft, int width, int area, uint8* dst, int count) { @@ -5902,13 +5268,12 @@ void CumulativeSumToAverageRow_SSE2(const int32* topleft, const int32* botleft, packssdw xmm5, xmm5 // 16 bit shorts // 4 pixel loop small blocks. - align 4 s4: // top left - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + 32] + movdqu xmm3, [eax + 48] // - top right psubd xmm0, [eax + edx * 4] @@ -5945,13 +5310,12 @@ void CumulativeSumToAverageRow_SSE2(const int32* topleft, const int32* botleft, jmp l4b // 4 pixel loop - align 4 l4: // top left - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + 32] - movdqa xmm3, [eax + 48] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + 32] + movdqu xmm3, [eax + 48] // - top right psubd xmm0, [eax + edx * 4] @@ -5998,9 +5362,8 @@ void CumulativeSumToAverageRow_SSE2(const int32* topleft, const int32* botleft, jl l1b // 1 pixel loop - align 4 l1: - movdqa xmm0, [eax] + movdqu xmm0, [eax] psubd xmm0, [eax + edx * 4] lea eax, [eax + 16] psubd xmm0, [esi] @@ -6039,7 +5402,6 @@ void ComputeCumulativeSumRow_SSE2(const uint8* row, int32* cumsum, jne l4b // 4 pixel loop - align 4 l4: movdqu xmm2, [eax] // 4 argb pixels 16 bytes. lea eax, [eax + 16] @@ -6056,26 +5418,26 @@ void ComputeCumulativeSumRow_SSE2(const uint8* row, int32* cumsum, punpckhwd xmm5, xmm1 paddd xmm0, xmm2 - movdqa xmm2, [esi] // previous row above. + movdqu xmm2, [esi] // previous row above. paddd xmm2, xmm0 paddd xmm0, xmm3 - movdqa xmm3, [esi + 16] + movdqu xmm3, [esi + 16] paddd xmm3, xmm0 paddd xmm0, xmm4 - movdqa xmm4, [esi + 32] + movdqu xmm4, [esi + 32] paddd xmm4, xmm0 paddd xmm0, xmm5 - movdqa xmm5, [esi + 48] + movdqu xmm5, [esi + 48] lea esi, [esi + 64] paddd xmm5, xmm0 - movdqa [edx], xmm2 - movdqa [edx + 16], xmm3 - movdqa [edx + 32], xmm4 - movdqa [edx + 48], xmm5 + movdqu [edx], xmm2 + movdqu [edx + 16], xmm3 + movdqu [edx + 32], xmm4 + movdqu [edx + 48], xmm5 lea edx, [edx + 64] sub ecx, 4 @@ -6086,7 +5448,6 @@ void ComputeCumulativeSumRow_SSE2(const uint8* row, int32* cumsum, jl l1b // 1 pixel loop - align 4 l1: movd xmm2, dword ptr [eax] // 1 argb pixel 4 bytes. lea eax, [eax + 4] @@ -6108,7 +5469,7 @@ void ComputeCumulativeSumRow_SSE2(const uint8* row, int32* cumsum, #ifdef HAS_ARGBAFFINEROW_SSE2 // Copy ARGB pixels from source image with slope to a row of destination. -__declspec(naked) __declspec(align(16)) +__declspec(naked) LIBYUV_API void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, uint8* dst_argb, const float* uv_dudv, int width) { @@ -6141,7 +5502,6 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, addps xmm4, xmm4 // dudv *= 4 // 4 pixel loop - align 4 l4: cvttps2dq xmm0, xmm2 // x, y float to int first 2 cvttps2dq xmm1, xmm3 // x, y float to int next 2 @@ -6163,9 +5523,9 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, movd xmm0, [eax + edi] // read pixel 3 punpckldq xmm6, xmm0 // combine pixel 2 and 3 addps xmm3, xmm4 // x, y += dx, dy next 2 - sub ecx, 4 movq qword ptr 8[edx], xmm6 lea edx, [edx + 16] + sub ecx, 4 jge l4 l4b: @@ -6173,7 +5533,6 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, jl l1b // 1 pixel loop - align 4 l1: cvttps2dq xmm0, xmm2 // x, y float to int packssdw xmm0, xmm0 // x, y as shorts @@ -6181,9 +5540,9 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, addps xmm2, xmm7 // x, y += dx, dy movd esi, xmm0 movd xmm0, [eax + esi] // copy a pixel - sub ecx, 1 movd [edx], xmm0 lea edx, [edx + 4] + sub ecx, 1 jge l1 l1b: pop edi @@ -6194,217 +5553,9 @@ void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, #endif // HAS_ARGBAFFINEROW_SSE2 #ifdef HAS_INTERPOLATEROW_AVX2 -// Bilinear filter 16x2 -> 16x1 -__declspec(naked) __declspec(align(16)) +// Bilinear filter 32x2 -> 32x1 +__declspec(naked) void InterpolateRow_AVX2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - __asm { - push esi - push edi - mov edi, [esp + 8 + 4] // dst_ptr - mov esi, [esp + 8 + 8] // src_ptr - mov edx, [esp + 8 + 12] // src_stride - mov ecx, [esp + 8 + 16] // dst_width - mov eax, [esp + 8 + 20] // source_y_fraction (0..255) - shr eax, 1 - // Dispatch to specialized filters if applicable. - cmp eax, 0 - je xloop100 // 0 / 128. Blend 100 / 0. - sub edi, esi - cmp eax, 32 - je xloop75 // 32 / 128 is 0.25. Blend 75 / 25. - cmp eax, 64 - je xloop50 // 64 / 128 is 0.50. Blend 50 / 50. - cmp eax, 96 - je xloop25 // 96 / 128 is 0.75. Blend 25 / 75. - - vmovd xmm0, eax // high fraction 0..127 - neg eax - add eax, 128 - vmovd xmm5, eax // low fraction 128..1 - vpunpcklbw xmm5, xmm5, xmm0 - vpunpcklwd xmm5, xmm5, xmm5 - vpxor ymm0, ymm0, ymm0 - vpermd ymm5, ymm0, ymm5 - - align 4 - xloop: - vmovdqu ymm0, [esi] - vmovdqu ymm2, [esi + edx] - vpunpckhbw ymm1, ymm0, ymm2 // mutates - vpunpcklbw ymm0, ymm0, ymm2 // mutates - vpmaddubsw ymm0, ymm0, ymm5 - vpmaddubsw ymm1, ymm1, ymm5 - vpsrlw ymm0, ymm0, 7 - vpsrlw ymm1, ymm1, 7 - vpackuswb ymm0, ymm0, ymm1 // unmutates - sub ecx, 32 - vmovdqu [esi + edi], ymm0 - lea esi, [esi + 32] - jg xloop - jmp xloop99 - - // Blend 25 / 75. - align 4 - xloop25: - vmovdqu ymm0, [esi] - vpavgb ymm0, ymm0, [esi + edx] - vpavgb ymm0, ymm0, [esi + edx] - sub ecx, 32 - vmovdqu [esi + edi], ymm0 - lea esi, [esi + 32] - jg xloop25 - jmp xloop99 - - // Blend 50 / 50. - align 4 - xloop50: - vmovdqu ymm0, [esi] - vpavgb ymm0, ymm0, [esi + edx] - sub ecx, 32 - vmovdqu [esi + edi], ymm0 - lea esi, [esi + 32] - jg xloop50 - jmp xloop99 - - // Blend 75 / 25. - align 4 - xloop75: - vmovdqu ymm0, [esi + edx] - vpavgb ymm0, ymm0, [esi] - vpavgb ymm0, ymm0, [esi] - sub ecx, 32 - vmovdqu [esi + edi], ymm0 - lea esi, [esi + 32] - jg xloop75 - jmp xloop99 - - // Blend 100 / 0 - Copy row unchanged. - align 4 - xloop100: - rep movsb - - xloop99: - pop edi - pop esi - vzeroupper - ret - } -} -#endif // HAS_INTERPOLATEROW_AVX2 - -#ifdef HAS_INTERPOLATEROW_SSSE3 -// Bilinear filter 16x2 -> 16x1 -__declspec(naked) __declspec(align(16)) -void InterpolateRow_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - __asm { - push esi - push edi - mov edi, [esp + 8 + 4] // dst_ptr - mov esi, [esp + 8 + 8] // src_ptr - mov edx, [esp + 8 + 12] // src_stride - mov ecx, [esp + 8 + 16] // dst_width - mov eax, [esp + 8 + 20] // source_y_fraction (0..255) - sub edi, esi - shr eax, 1 - // Dispatch to specialized filters if applicable. - cmp eax, 0 - je xloop100 // 0 / 128. Blend 100 / 0. - cmp eax, 32 - je xloop75 // 32 / 128 is 0.25. Blend 75 / 25. - cmp eax, 64 - je xloop50 // 64 / 128 is 0.50. Blend 50 / 50. - cmp eax, 96 - je xloop25 // 96 / 128 is 0.75. Blend 25 / 75. - - movd xmm0, eax // high fraction 0..127 - neg eax - add eax, 128 - movd xmm5, eax // low fraction 128..1 - punpcklbw xmm5, xmm0 - punpcklwd xmm5, xmm5 - pshufd xmm5, xmm5, 0 - - align 4 - xloop: - movdqa xmm0, [esi] - movdqa xmm2, [esi + edx] - movdqa xmm1, xmm0 - punpcklbw xmm0, xmm2 - punpckhbw xmm1, xmm2 - pmaddubsw xmm0, xmm5 - pmaddubsw xmm1, xmm5 - psrlw xmm0, 7 - psrlw xmm1, 7 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop - jmp xloop99 - - // Blend 25 / 75. - align 4 - xloop25: - movdqa xmm0, [esi] - movdqa xmm1, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop25 - jmp xloop99 - - // Blend 50 / 50. - align 4 - xloop50: - movdqa xmm0, [esi] - movdqa xmm1, [esi + edx] - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop50 - jmp xloop99 - - // Blend 75 / 25. - align 4 - xloop75: - movdqa xmm1, [esi] - movdqa xmm0, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop75 - jmp xloop99 - - // Blend 100 / 0 - Copy row unchanged. - align 4 - xloop100: - movdqa xmm0, [esi] - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop100 - - xloop99: - pop edi - pop esi - ret - } -} -#endif // HAS_INTERPOLATEROW_SSSE3 - -#ifdef HAS_INTERPOLATEROW_SSE2 -// Bilinear filter 16x2 -> 16x1 -__declspec(naked) __declspec(align(16)) -void InterpolateRow_SSE2(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride, int dst_width, int source_y_fraction) { __asm { @@ -6415,201 +5566,141 @@ void InterpolateRow_SSE2(uint8* dst_ptr, const uint8* src_ptr, mov edx, [esp + 8 + 12] // src_stride mov ecx, [esp + 8 + 16] // dst_width mov eax, [esp + 8 + 20] // source_y_fraction (0..255) - sub edi, esi // Dispatch to specialized filters if applicable. cmp eax, 0 je xloop100 // 0 / 256. Blend 100 / 0. - cmp eax, 64 - je xloop75 // 64 / 256 is 0.25. Blend 75 / 25. + sub edi, esi cmp eax, 128 - je xloop50 // 128 / 256 is 0.50. Blend 50 / 50. - cmp eax, 192 - je xloop25 // 192 / 256 is 0.75. Blend 25 / 75. + je xloop50 // 128 /256 is 0.50. Blend 50 / 50. - movd xmm5, eax // xmm5 = y fraction - punpcklbw xmm5, xmm5 - psrlw xmm5, 1 - punpcklwd xmm5, xmm5 - punpckldq xmm5, xmm5 - punpcklqdq xmm5, xmm5 - pxor xmm4, xmm4 + vmovd xmm0, eax // high fraction 0..255 + neg eax + add eax, 256 + vmovd xmm5, eax // low fraction 256..1 + vpunpcklbw xmm5, xmm5, xmm0 + vpunpcklwd xmm5, xmm5, xmm5 + vbroadcastss ymm5, xmm5 + + mov eax, 0x80808080 // 128b for bias and rounding. + vmovd xmm4, eax + vbroadcastss ymm4, xmm4 - align 4 xloop: - movdqa xmm0, [esi] // row0 - movdqa xmm2, [esi + edx] // row1 - movdqa xmm1, xmm0 - movdqa xmm3, xmm2 - punpcklbw xmm2, xmm4 - punpckhbw xmm3, xmm4 - punpcklbw xmm0, xmm4 - punpckhbw xmm1, xmm4 - psubw xmm2, xmm0 // row1 - row0 - psubw xmm3, xmm1 - paddw xmm2, xmm2 // 9 bits * 15 bits = 8.16 - paddw xmm3, xmm3 - pmulhw xmm2, xmm5 // scale diff - pmulhw xmm3, xmm5 - paddw xmm0, xmm2 // sum rows - paddw xmm1, xmm3 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] + vmovdqu ymm0, [esi] + vmovdqu ymm2, [esi + edx] + vpunpckhbw ymm1, ymm0, ymm2 // mutates + vpunpcklbw ymm0, ymm0, ymm2 + vpsubb ymm1, ymm1, ymm4 // bias to signed image + vpsubb ymm0, ymm0, ymm4 + vpmaddubsw ymm1, ymm5, ymm1 + vpmaddubsw ymm0, ymm5, ymm0 + vpaddw ymm1, ymm1, ymm4 // unbias and round + vpaddw ymm0, ymm0, ymm4 + vpsrlw ymm1, ymm1, 8 + vpsrlw ymm0, ymm0, 8 + vpackuswb ymm0, ymm0, ymm1 // unmutates + vmovdqu [esi + edi], ymm0 + lea esi, [esi + 32] + sub ecx, 32 jg xloop jmp xloop99 - // Blend 25 / 75. - align 4 - xloop25: - movdqa xmm0, [esi] - movdqa xmm1, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop25 - jmp xloop99 + // Blend 50 / 50. + xloop50: + vmovdqu ymm0, [esi] + vpavgb ymm0, ymm0, [esi + edx] + vmovdqu [esi + edi], ymm0 + lea esi, [esi + 32] + sub ecx, 32 + jg xloop50 + jmp xloop99 - // Blend 50 / 50. - align 4 - xloop50: - movdqa xmm0, [esi] - movdqa xmm1, [esi + edx] - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop50 - jmp xloop99 - - // Blend 75 / 25. - align 4 - xloop75: - movdqa xmm1, [esi] - movdqa xmm0, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop75 - jmp xloop99 - - // Blend 100 / 0 - Copy row unchanged. - align 4 - xloop100: - movdqa xmm0, [esi] - sub ecx, 16 - movdqa [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop100 + // Blend 100 / 0 - Copy row unchanged. + xloop100: + rep movsb xloop99: pop edi pop esi + vzeroupper ret } } -#endif // HAS_INTERPOLATEROW_SSE2 +#endif // HAS_INTERPOLATEROW_AVX2 // Bilinear filter 16x2 -> 16x1 -__declspec(naked) __declspec(align(16)) -void InterpolateRow_Unaligned_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { +// TODO(fbarchard): Consider allowing 256 using memcpy. +__declspec(naked) +void InterpolateRow_SSSE3(uint8* dst_ptr, const uint8* src_ptr, + ptrdiff_t src_stride, int dst_width, + int source_y_fraction) { __asm { push esi push edi + mov edi, [esp + 8 + 4] // dst_ptr mov esi, [esp + 8 + 8] // src_ptr mov edx, [esp + 8 + 12] // src_stride mov ecx, [esp + 8 + 16] // dst_width mov eax, [esp + 8 + 20] // source_y_fraction (0..255) sub edi, esi - shr eax, 1 // Dispatch to specialized filters if applicable. cmp eax, 0 - je xloop100 // 0 / 128. Blend 100 / 0. - cmp eax, 32 - je xloop75 // 32 / 128 is 0.25. Blend 75 / 25. - cmp eax, 64 - je xloop50 // 64 / 128 is 0.50. Blend 50 / 50. - cmp eax, 96 - je xloop25 // 96 / 128 is 0.75. Blend 25 / 75. + je xloop100 // 0 /256. Blend 100 / 0. + cmp eax, 128 + je xloop50 // 128 / 256 is 0.50. Blend 50 / 50. - movd xmm0, eax // high fraction 0..127 + movd xmm0, eax // high fraction 0..255 neg eax - add eax, 128 - movd xmm5, eax // low fraction 128..1 + add eax, 256 + movd xmm5, eax // low fraction 255..1 punpcklbw xmm5, xmm0 punpcklwd xmm5, xmm5 pshufd xmm5, xmm5, 0 + mov eax, 0x80808080 // 128 for biasing image to signed. + movd xmm4, eax + pshufd xmm4, xmm4, 0x00 - align 4 xloop: movdqu xmm0, [esi] movdqu xmm2, [esi + edx] movdqu xmm1, xmm0 punpcklbw xmm0, xmm2 punpckhbw xmm1, xmm2 - pmaddubsw xmm0, xmm5 - pmaddubsw xmm1, xmm5 - psrlw xmm0, 7 - psrlw xmm1, 7 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 + psubb xmm0, xmm4 // bias image by -128 + psubb xmm1, xmm4 + movdqa xmm2, xmm5 + movdqa xmm3, xmm5 + pmaddubsw xmm2, xmm0 + pmaddubsw xmm3, xmm1 + paddw xmm2, xmm4 + paddw xmm3, xmm4 + psrlw xmm2, 8 + psrlw xmm3, 8 + packuswb xmm2, xmm3 + movdqu [esi + edi], xmm2 lea esi, [esi + 16] + sub ecx, 16 jg xloop jmp xloop99 - // Blend 25 / 75. - align 4 - xloop25: - movdqu xmm0, [esi] - movdqu xmm1, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop25 - jmp xloop99 - // Blend 50 / 50. - align 4 xloop50: movdqu xmm0, [esi] movdqu xmm1, [esi + edx] pavgb xmm0, xmm1 - sub ecx, 16 movdqu [esi + edi], xmm0 lea esi, [esi + 16] + sub ecx, 16 jg xloop50 jmp xloop99 - // Blend 75 / 25. - align 4 - xloop75: - movdqu xmm1, [esi] - movdqu xmm0, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop75 - jmp xloop99 - // Blend 100 / 0 - Copy row unchanged. - align 4 xloop100: movdqu xmm0, [esi] - sub ecx, 16 movdqu [esi + edi], xmm0 lea esi, [esi + 16] + sub ecx, 16 jg xloop100 xloop99: @@ -6619,303 +5710,53 @@ void InterpolateRow_Unaligned_SSSE3(uint8* dst_ptr, const uint8* src_ptr, } } -#ifdef HAS_INTERPOLATEROW_SSE2 -// Bilinear filter 16x2 -> 16x1 -__declspec(naked) __declspec(align(16)) -void InterpolateRow_Unaligned_SSE2(uint8* dst_ptr, const uint8* src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) { - __asm { - push esi - push edi - mov edi, [esp + 8 + 4] // dst_ptr - mov esi, [esp + 8 + 8] // src_ptr - mov edx, [esp + 8 + 12] // src_stride - mov ecx, [esp + 8 + 16] // dst_width - mov eax, [esp + 8 + 20] // source_y_fraction (0..255) - sub edi, esi - // Dispatch to specialized filters if applicable. - cmp eax, 0 - je xloop100 // 0 / 256. Blend 100 / 0. - cmp eax, 64 - je xloop75 // 64 / 256 is 0.25. Blend 75 / 25. - cmp eax, 128 - je xloop50 // 128 / 256 is 0.50. Blend 50 / 50. - cmp eax, 192 - je xloop25 // 192 / 256 is 0.75. Blend 25 / 75. - - movd xmm5, eax // xmm5 = y fraction - punpcklbw xmm5, xmm5 - psrlw xmm5, 1 - punpcklwd xmm5, xmm5 - punpckldq xmm5, xmm5 - punpcklqdq xmm5, xmm5 - pxor xmm4, xmm4 - - align 4 - xloop: - movdqu xmm0, [esi] // row0 - movdqu xmm2, [esi + edx] // row1 - movdqu xmm1, xmm0 - movdqu xmm3, xmm2 - punpcklbw xmm2, xmm4 - punpckhbw xmm3, xmm4 - punpcklbw xmm0, xmm4 - punpckhbw xmm1, xmm4 - psubw xmm2, xmm0 // row1 - row0 - psubw xmm3, xmm1 - paddw xmm2, xmm2 // 9 bits * 15 bits = 8.16 - paddw xmm3, xmm3 - pmulhw xmm2, xmm5 // scale diff - pmulhw xmm3, xmm5 - paddw xmm0, xmm2 // sum rows - paddw xmm1, xmm3 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop - jmp xloop99 - - // Blend 25 / 75. - align 4 - xloop25: - movdqu xmm0, [esi] - movdqu xmm1, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop25 - jmp xloop99 - - // Blend 50 / 50. - align 4 - xloop50: - movdqu xmm0, [esi] - movdqu xmm1, [esi + edx] - pavgb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop50 - jmp xloop99 - - // Blend 75 / 25. - align 4 - xloop75: - movdqu xmm1, [esi] - movdqu xmm0, [esi + edx] - pavgb xmm0, xmm1 - pavgb xmm0, xmm1 - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop75 - jmp xloop99 - - // Blend 100 / 0 - Copy row unchanged. - align 4 - xloop100: - movdqu xmm0, [esi] - sub ecx, 16 - movdqu [esi + edi], xmm0 - lea esi, [esi + 16] - jg xloop100 - - xloop99: - pop edi - pop esi - ret - } -} -#endif // HAS_INTERPOLATEROW_SSE2 - -__declspec(naked) __declspec(align(16)) -void HalfRow_SSE2(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_uv - mov edx, [esp + 4 + 8] // src_uv_stride - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - sub edi, eax - - align 4 - convertloop: - movdqa xmm0, [eax] - pavgb xmm0, [eax + edx] - sub ecx, 16 - movdqa [eax + edi], xmm0 - lea eax, [eax + 16] - jg convertloop - pop edi - ret - } -} - -#ifdef HAS_HALFROW_AVX2 -__declspec(naked) __declspec(align(16)) -void HalfRow_AVX2(const uint8* src_uv, int src_uv_stride, - uint8* dst_uv, int pix) { - __asm { - push edi - mov eax, [esp + 4 + 4] // src_uv - mov edx, [esp + 4 + 8] // src_uv_stride - mov edi, [esp + 4 + 12] // dst_v - mov ecx, [esp + 4 + 16] // pix - sub edi, eax - - align 4 - convertloop: - vmovdqu ymm0, [eax] - vpavgb ymm0, ymm0, [eax + edx] - sub ecx, 32 - vmovdqu [eax + edi], ymm0 - lea eax, [eax + 32] - jg convertloop - - pop edi - vzeroupper - ret - } -} -#endif // HAS_HALFROW_AVX2 - -__declspec(naked) __declspec(align(16)) -void ARGBToBayerRow_SSSE3(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - __asm { - mov eax, [esp + 4] // src_argb - mov edx, [esp + 8] // dst_bayer - movd xmm5, [esp + 12] // selector - mov ecx, [esp + 16] // pix - pshufd xmm5, xmm5, 0 - - align 4 - wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - pshufb xmm0, xmm5 - pshufb xmm1, xmm5 - punpckldq xmm0, xmm1 - sub ecx, 8 - movq qword ptr [edx], xmm0 - lea edx, [edx + 8] - jg wloop - ret - } -} - -// Specialized ARGB to Bayer that just isolates G channel. -__declspec(naked) __declspec(align(16)) -void ARGBToBayerGGRow_SSE2(const uint8* src_argb, uint8* dst_bayer, - uint32 selector, int pix) { - __asm { - mov eax, [esp + 4] // src_argb - mov edx, [esp + 8] // dst_bayer - // selector - mov ecx, [esp + 16] // pix - pcmpeqb xmm5, xmm5 // generate mask 0x000000ff - psrld xmm5, 24 - - align 4 - wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - psrld xmm0, 8 // Move green to bottom. - psrld xmm1, 8 - pand xmm0, xmm5 - pand xmm1, xmm5 - packssdw xmm0, xmm1 - packuswb xmm0, xmm1 - sub ecx, 8 - movq qword ptr [edx], xmm0 - lea edx, [edx + 8] - jg wloop - ret - } -} - // For BGRAToARGB, ABGRToARGB, RGBAToARGB, and ARGBToRGBA. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBShuffleRow_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_argb mov ecx, [esp + 12] // shuffler - movdqa xmm5, [ecx] - mov ecx, [esp + 16] // pix + movdqu xmm5, [ecx] + mov ecx, [esp + 16] // width - align 4 - wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - pshufb xmm0, xmm5 - pshufb xmm1, xmm5 - sub ecx, 8 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 - lea edx, [edx + 32] - jg wloop - ret - } -} - -__declspec(naked) __declspec(align(16)) -void ARGBShuffleRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { - __asm { - mov eax, [esp + 4] // src_argb - mov edx, [esp + 8] // dst_argb - mov ecx, [esp + 12] // shuffler - movdqa xmm5, [ecx] - mov ecx, [esp + 16] // pix - - align 4 wloop: movdqu xmm0, [eax] movdqu xmm1, [eax + 16] lea eax, [eax + 32] pshufb xmm0, xmm5 pshufb xmm1, xmm5 - sub ecx, 8 movdqu [edx], xmm0 movdqu [edx + 16], xmm1 lea edx, [edx + 32] + sub ecx, 8 jg wloop ret } } #ifdef HAS_ARGBSHUFFLEROW_AVX2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBShuffleRow_AVX2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { __asm { mov eax, [esp + 4] // src_argb mov edx, [esp + 8] // dst_argb mov ecx, [esp + 12] // shuffler vbroadcastf128 ymm5, [ecx] // same shuffle in high as low. - mov ecx, [esp + 16] // pix + mov ecx, [esp + 16] // width - align 4 wloop: vmovdqu ymm0, [eax] vmovdqu ymm1, [eax + 32] lea eax, [eax + 64] vpshufb ymm0, ymm0, ymm5 vpshufb ymm1, ymm1, ymm5 - sub ecx, 16 vmovdqu [edx], ymm0 vmovdqu [edx + 32], ymm1 lea edx, [edx + 64] + sub ecx, 16 jg wloop vzeroupper @@ -6924,16 +5765,16 @@ void ARGBShuffleRow_AVX2(const uint8* src_argb, uint8* dst_argb, } #endif // HAS_ARGBSHUFFLEROW_AVX2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, - const uint8* shuffler, int pix) { + const uint8* shuffler, int width) { __asm { push ebx push esi mov eax, [esp + 8 + 4] // src_argb mov edx, [esp + 8 + 8] // dst_argb mov esi, [esp + 8 + 12] // shuffler - mov ecx, [esp + 8 + 16] // pix + mov ecx, [esp + 8 + 16] // width pxor xmm5, xmm5 mov ebx, [esi] // shuffler @@ -6966,7 +5807,6 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, jg shuf_any1 jmp shuf99 - align 4 shuf_0123: movdqu xmm0, [eax] lea eax, [eax + 16] @@ -6978,13 +5818,12 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, pshufhw xmm1, xmm1, 01Bh pshuflw xmm1, xmm1, 01Bh packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg shuf_0123 jmp shuf99 - align 4 shuf_0321: movdqu xmm0, [eax] lea eax, [eax + 16] @@ -6996,13 +5835,12 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, pshufhw xmm1, xmm1, 039h pshuflw xmm1, xmm1, 039h packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg shuf_0321 jmp shuf99 - align 4 shuf_2103: movdqu xmm0, [eax] lea eax, [eax + 16] @@ -7014,13 +5852,12 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, pshufhw xmm1, xmm1, 093h pshuflw xmm1, xmm1, 093h packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg shuf_2103 jmp shuf99 - align 4 shuf_3012: movdqu xmm0, [eax] lea eax, [eax + 16] @@ -7032,9 +5869,9 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, pshufhw xmm1, xmm1, 0C6h pshuflw xmm1, xmm1, 0C6h packuswb xmm0, xmm1 - sub ecx, 4 movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg shuf_3012 shuf99: @@ -7050,7 +5887,7 @@ void ARGBShuffleRow_SSE2(const uint8* src_argb, uint8* dst_argb, // UYVY - Macro-pixel = 2 image pixels // U0Y0V0Y1 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I422ToYUY2Row_SSE2(const uint8* src_y, const uint8* src_u, const uint8* src_v, @@ -7065,7 +5902,6 @@ void I422ToYUY2Row_SSE2(const uint8* src_y, mov ecx, [esp + 8 + 20] // width sub edx, esi - align 4 convertloop: movq xmm2, qword ptr [esi] // U movq xmm3, qword ptr [esi + edx] // V @@ -7088,7 +5924,7 @@ void I422ToYUY2Row_SSE2(const uint8* src_y, } } -__declspec(naked) __declspec(align(16)) +__declspec(naked) void I422ToUYVYRow_SSE2(const uint8* src_y, const uint8* src_u, const uint8* src_v, @@ -7103,7 +5939,6 @@ void I422ToUYVYRow_SSE2(const uint8* src_y, mov ecx, [esp + 8 + 20] // width sub edx, esi - align 4 convertloop: movq xmm2, qword ptr [esi] // U movq xmm3, qword ptr [esi + edx] // V @@ -7127,7 +5962,7 @@ void I422ToUYVYRow_SSE2(const uint8* src_y, } #ifdef HAS_ARGBPOLYNOMIALROW_SSE2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBPolynomialRow_SSE2(const uint8* src_argb, uint8* dst_argb, const float* poly, int width) { @@ -7140,7 +5975,6 @@ void ARGBPolynomialRow_SSE2(const uint8* src_argb, pxor xmm3, xmm3 // 0 constant for zero extending bytes to ints. // 2 pixel loop. - align 4 convertloop: // pmovzxbd xmm0, dword ptr [eax] // BGRA pixel // pmovzxbd xmm4, dword ptr [eax + 4] // BGRA pixel @@ -7176,9 +6010,9 @@ void ARGBPolynomialRow_SSE2(const uint8* src_argb, cvttps2dq xmm4, xmm4 packuswb xmm0, xmm4 packuswb xmm0, xmm0 - sub ecx, 2 movq qword ptr [edx], xmm0 lea edx, [edx + 8] + sub ecx, 2 jg convertloop pop esi ret @@ -7187,7 +6021,7 @@ void ARGBPolynomialRow_SSE2(const uint8* src_argb, #endif // HAS_ARGBPOLYNOMIALROW_SSE2 #ifdef HAS_ARGBPOLYNOMIALROW_AVX2 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBPolynomialRow_AVX2(const uint8* src_argb, uint8* dst_argb, const float* poly, int width) { @@ -7202,7 +6036,6 @@ void ARGBPolynomialRow_AVX2(const uint8* src_argb, mov ecx, [esp + 16] /* width */ // 2 pixel loop. - align 4 convertloop: vpmovzxbd ymm0, qword ptr [eax] // 2 BGRA pixels lea eax, [eax + 8] @@ -7216,9 +6049,9 @@ void ARGBPolynomialRow_AVX2(const uint8* src_argb, vpackusdw ymm0, ymm0, ymm0 // b0g0r0a0_00000000_b0g0r0a0_00000000 vpermq ymm0, ymm0, 0xd8 // b0g0r0a0_b0g0r0a0_00000000_00000000 vpackuswb xmm0, xmm0, xmm0 // bgrabgra_00000000_00000000_00000000 - sub ecx, 2 vmovq qword ptr [edx], xmm0 lea edx, [edx + 8] + sub ecx, 2 jg convertloop vzeroupper ret @@ -7228,7 +6061,7 @@ void ARGBPolynomialRow_AVX2(const uint8* src_argb, #ifdef HAS_ARGBCOLORTABLEROW_X86 // Tranform ARGB pixels with color table. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { __asm { @@ -7238,7 +6071,6 @@ void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, mov ecx, [esp + 4 + 12] /* width */ // 1 pixel loop. - align 4 convertloop: movzx edx, byte ptr [eax] lea eax, [eax + 4] @@ -7263,7 +6095,7 @@ void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, #ifdef HAS_RGBCOLORTABLEROW_X86 // Tranform RGB pixels with color table. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { __asm { push esi @@ -7272,7 +6104,6 @@ void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { mov ecx, [esp + 4 + 12] /* width */ // 1 pixel loop. - align 4 convertloop: movzx edx, byte ptr [eax] lea eax, [eax + 4] @@ -7295,7 +6126,7 @@ void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { #ifdef HAS_ARGBLUMACOLORTABLEROW_SSSE3 // Tranform RGB pixels with luma table. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, uint8* dst_argb, int width, const uint8* luma, uint32 lumacoeff) { @@ -7314,9 +6145,8 @@ void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, uint8* dst_argb, pxor xmm5, xmm5 // 4 pixel loop. - align 4 convertloop: - movdqu xmm0, qword ptr [eax] // generate luma ptr + movdqu xmm0, xmmword ptr [eax] // generate luma ptr pmaddubsw xmm0, xmm3 phaddw xmm0, xmm0 pand xmm0, xmm4 // mask out low bits @@ -7381,9 +6211,9 @@ void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, uint8* dst_argb, movzx edx, byte ptr [eax + 15] // copy alpha. mov byte ptr [edi + 15], dl - sub ecx, 4 lea eax, [eax + 16] lea edi, [edi + 16] + sub ecx, 4 jg convertloop pop edi @@ -7394,7 +6224,7 @@ void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, uint8* dst_argb, #endif // HAS_ARGBLUMACOLORTABLEROW_SSSE3 #endif // defined(_M_X64) -#endif // !defined(LIBYUV_DISABLE_X86) && defined(_MSC_VER) +#endif // !defined(LIBYUV_DISABLE_X86) && (defined(_M_IX86) || defined(_M_X64)) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/row_x86.asm b/TMessagesProj/jni/libyuv/source/row_x86.asm deleted file mode 100644 index 0cb326f8..00000000 --- a/TMessagesProj/jni/libyuv/source/row_x86.asm +++ /dev/null @@ -1,146 +0,0 @@ -; -; Copyright 2012 The LibYuv Project Authors. All rights reserved. -; -; Use of this source code is governed by a BSD-style license -; that can be found in the LICENSE file in the root of the source -; tree. An additional intellectual property rights grant can be found -; in the file PATENTS. All contributing project authors may -; be found in the AUTHORS file in the root of the source tree. -; - -%ifdef __YASM_VERSION_ID__ -%if __YASM_VERSION_ID__ < 01020000h -%error AVX2 is supported only by yasm 1.2.0 or later. -%endif -%endif -%include "x86inc.asm" - -SECTION .text - -; cglobal numeric constants are parameters, gpr regs, mm regs - -; void YUY2ToYRow_SSE2(const uint8* src_yuy2, uint8* dst_y, int pix) - -%macro YUY2TOYROW 2-3 -cglobal %1ToYRow%3, 3, 3, 3, src_yuy2, dst_y, pix -%ifidn %1,YUY2 - pcmpeqb m2, m2, m2 ; generate mask 0x00ff00ff - psrlw m2, m2, 8 -%endif - - ALIGN 4 -.convertloop: - mov%2 m0, [src_yuy2q] - mov%2 m1, [src_yuy2q + mmsize] - lea src_yuy2q, [src_yuy2q + mmsize * 2] -%ifidn %1,YUY2 - pand m0, m0, m2 ; YUY2 even bytes are Y - pand m1, m1, m2 -%else - psrlw m0, m0, 8 ; UYVY odd bytes are Y - psrlw m1, m1, 8 -%endif - packuswb m0, m0, m1 -%if cpuflag(AVX2) - vpermq m0, m0, 0xd8 -%endif - sub pixd, mmsize - mov%2 [dst_yq], m0 - lea dst_yq, [dst_yq + mmsize] - jg .convertloop - REP_RET -%endmacro - -; TODO(fbarchard): Remove MMX. Add SSSE3 pshufb version. -INIT_MMX MMX -YUY2TOYROW YUY2,a, -YUY2TOYROW YUY2,u,_Unaligned -YUY2TOYROW UYVY,a, -YUY2TOYROW UYVY,u,_Unaligned -INIT_XMM SSE2 -YUY2TOYROW YUY2,a, -YUY2TOYROW YUY2,u,_Unaligned -YUY2TOYROW UYVY,a, -YUY2TOYROW UYVY,u,_Unaligned -INIT_YMM AVX2 -YUY2TOYROW YUY2,a, -YUY2TOYROW UYVY,a, - -; void SplitUVRow_SSE2(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) - -%macro SplitUVRow 1-2 -cglobal SplitUVRow%2, 4, 4, 5, src_uv, dst_u, dst_v, pix - pcmpeqb m4, m4, m4 ; generate mask 0x00ff00ff - psrlw m4, m4, 8 - sub dst_vq, dst_uq - - ALIGN 4 -.convertloop: - mov%1 m0, [src_uvq] - mov%1 m1, [src_uvq + mmsize] - lea src_uvq, [src_uvq + mmsize * 2] - psrlw m2, m0, 8 ; odd bytes - psrlw m3, m1, 8 - pand m0, m0, m4 ; even bytes - pand m1, m1, m4 - packuswb m0, m0, m1 - packuswb m2, m2, m3 -%if cpuflag(AVX2) - vpermq m0, m0, 0xd8 - vpermq m2, m2, 0xd8 -%endif - mov%1 [dst_uq], m0 - mov%1 [dst_uq + dst_vq], m2 - lea dst_uq, [dst_uq + mmsize] - sub pixd, mmsize - jg .convertloop - REP_RET -%endmacro - -INIT_MMX MMX -SplitUVRow a, -SplitUVRow u,_Unaligned -INIT_XMM SSE2 -SplitUVRow a, -SplitUVRow u,_Unaligned -INIT_YMM AVX2 -SplitUVRow a, - -; void MergeUVRow_SSE2(const uint8* src_u, const uint8* src_v, uint8* dst_uv, -; int width); - -%macro MergeUVRow_ 1-2 -cglobal MergeUVRow_%2, 4, 4, 3, src_u, src_v, dst_uv, pix - sub src_vq, src_uq - - ALIGN 4 -.convertloop: - mov%1 m0, [src_uq] - mov%1 m1, [src_vq] - lea src_uq, [src_uq + mmsize] - punpcklbw m2, m0, m1 // first 8 UV pairs - punpckhbw m0, m0, m1 // next 8 UV pairs -%if cpuflag(AVX2) - vperm2i128 m1, m2, m0, 0x20 // low 128 of ymm2 and low 128 of ymm0 - vperm2i128 m2, m2, m0, 0x31 // high 128 of ymm2 and high 128 of ymm0 - mov%1 [dst_uvq], m1 - mov%1 [dst_uvq + mmsize], m2 -%else - mov%1 [dst_uvq], m2 - mov%1 [dst_uvq + mmsize], m0 -%endif - lea dst_uvq, [dst_uvq + mmsize * 2] - sub pixd, mmsize - jg .convertloop - REP_RET -%endmacro - -INIT_MMX MMX -MergeUVRow_ a, -MergeUVRow_ u,_Unaligned -INIT_XMM SSE2 -MergeUVRow_ a, -MergeUVRow_ u,_Unaligned -INIT_YMM AVX2 -MergeUVRow_ a, - diff --git a/TMessagesProj/jni/libyuv/source/scale.cc b/TMessagesProj/jni/libyuv/source/scale.cc index 5b33b5f0..595314f3 100644 --- a/TMessagesProj/jni/libyuv/source/scale.cc +++ b/TMessagesProj/jni/libyuv/source/scale.cc @@ -23,9 +23,6 @@ namespace libyuv { extern "C" { #endif -// Remove this macro if OVERREAD is safe. -#define AVOID_OVERREAD 1 - static __inline int Abs(int v) { return v >= 0 ? v : -v; } @@ -44,9 +41,8 @@ static void ScalePlaneDown2(int src_width, int src_height, int y; void (*ScaleRowDown2)(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) = - filtering == kFilterNone ? ScaleRowDown2_C : - (filtering == kFilterLinear ? ScaleRowDown2Linear_C : - ScaleRowDown2Box_C); + filtering == kFilterNone ? ScaleRowDown2_C : + (filtering == kFilterLinear ? ScaleRowDown2Linear_C : ScaleRowDown2Box_C); int row_stride = src_stride << 1; if (!filtering) { src_ptr += src_stride; // Point to odd rows. @@ -54,23 +50,42 @@ static void ScalePlaneDown2(int src_width, int src_height, } #if defined(HAS_SCALEROWDOWN2_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) { - ScaleRowDown2 = filtering ? ScaleRowDown2Box_NEON : ScaleRowDown2_NEON; - } -#elif defined(HAS_SCALEROWDOWN2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) { - ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Unaligned_SSE2 : - (filtering == kFilterLinear ? ScaleRowDown2Linear_Unaligned_SSE2 : - ScaleRowDown2Box_Unaligned_SSE2); - if (IS_ALIGNED(src_ptr, 16) && - IS_ALIGNED(src_stride, 16) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_SSE2 : - (filtering == kFilterLinear ? ScaleRowDown2Linear_SSE2 : - ScaleRowDown2Box_SSE2); + if (TestCpuFlag(kCpuHasNEON)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_NEON : + (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_NEON : + ScaleRowDown2Box_Any_NEON); + if (IS_ALIGNED(dst_width, 16)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_NEON : + (filtering == kFilterLinear ? ScaleRowDown2Linear_NEON : + ScaleRowDown2Box_NEON); } } -#elif defined(HAS_SCALEROWDOWN2_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN2_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_SSSE3 : + (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3 : + ScaleRowDown2Box_Any_SSSE3); + if (IS_ALIGNED(dst_width, 16)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_SSSE3 : + (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3 : + ScaleRowDown2Box_SSSE3); + } + } +#endif +#if defined(HAS_SCALEROWDOWN2_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Any_AVX2 : + (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2 : + ScaleRowDown2Box_Any_AVX2); + if (IS_ALIGNED(dst_width, 32)) { + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2 : + (filtering == kFilterLinear ? ScaleRowDown2Linear_AVX2 : + ScaleRowDown2Box_AVX2); + } + } +#endif +#if defined(HAS_SCALEROWDOWN2_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(row_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -112,21 +127,15 @@ static void ScalePlaneDown2_16(int src_width, int src_height, ScaleRowDown2 = filtering ? ScaleRowDown2Box_16_NEON : ScaleRowDown2_16_NEON; } -#elif defined(HAS_SCALEROWDOWN2_16_SSE2) +#endif +#if defined(HAS_SCALEROWDOWN2_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) { - ScaleRowDown2 = filtering == kFilterNone ? - ScaleRowDown2_Unaligned_16_SSE2 : - (filtering == kFilterLinear ? ScaleRowDown2Linear_Unaligned_16_SSE2 : - ScaleRowDown2Box_Unaligned_16_SSE2); - if (IS_ALIGNED(src_ptr, 16) && - IS_ALIGNED(src_stride, 16) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_SSE2 : - (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2 : - ScaleRowDown2Box_16_SSE2); - } + ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_SSE2 : + (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2 : + ScaleRowDown2Box_16_SSE2); } -#elif defined(HAS_SCALEROWDOWN2_16_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN2_16_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(row_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -165,16 +174,33 @@ static void ScalePlaneDown4(int src_width, int src_height, src_stride = 0; } #if defined(HAS_SCALEROWDOWN4_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) { - ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON; + if (TestCpuFlag(kCpuHasNEON)) { + ScaleRowDown4 = filtering ? + ScaleRowDown4Box_Any_NEON : ScaleRowDown4_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON; + } } -#elif defined(HAS_SCALEROWDOWN4_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(dst_width, 8) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSE2 : ScaleRowDown4_SSE2; +#endif +#if defined(HAS_SCALEROWDOWN4_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { + ScaleRowDown4 = filtering ? + ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3; + if (IS_ALIGNED(dst_width, 8)) { + ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3; + } } -#elif defined(HAS_SCALEROWDOWN4_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN4_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ScaleRowDown4 = filtering ? + ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2; + if (IS_ALIGNED(dst_width, 16)) { + ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2; + } + } +#endif +#if defined(HAS_SCALEROWDOWN4_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(row_stride, 4) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -212,14 +238,14 @@ static void ScalePlaneDown4_16(int src_width, int src_height, ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_NEON : ScaleRowDown4_16_NEON; } -#elif defined(HAS_SCALEROWDOWN4_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && - IS_ALIGNED(dst_width, 8) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { +#endif +#if defined(HAS_SCALEROWDOWN4_16_SSE2) + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_SSE2 : ScaleRowDown4_16_SSE2; } -#elif defined(HAS_SCALEROWDOWN4_16_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN4_16_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(row_stride, 4) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -260,25 +286,42 @@ static void ScalePlaneDown34(int src_width, int src_height, ScaleRowDown34_1 = ScaleRowDown34_1_Box_C; } #if defined(HAS_SCALEROWDOWN34_NEON) - if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) { + if (TestCpuFlag(kCpuHasNEON)) { if (!filtering) { - ScaleRowDown34_0 = ScaleRowDown34_NEON; - ScaleRowDown34_1 = ScaleRowDown34_NEON; + ScaleRowDown34_0 = ScaleRowDown34_Any_NEON; + ScaleRowDown34_1 = ScaleRowDown34_Any_NEON; } else { - ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON; - ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON; + ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_NEON; + ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_NEON; + } + if (dst_width % 24 == 0) { + if (!filtering) { + ScaleRowDown34_0 = ScaleRowDown34_NEON; + ScaleRowDown34_1 = ScaleRowDown34_NEON; + } else { + ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON; + ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON; + } } } #endif #if defined(HAS_SCALEROWDOWN34_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { + if (TestCpuFlag(kCpuHasSSSE3)) { if (!filtering) { - ScaleRowDown34_0 = ScaleRowDown34_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_SSSE3; + ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3; + ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3; } else { - ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3; + ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3; + ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3; + } + if (dst_width % 24 == 0) { + if (!filtering) { + ScaleRowDown34_0 = ScaleRowDown34_SSSE3; + ScaleRowDown34_1 = ScaleRowDown34_SSSE3; + } else { + ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3; + ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3; + } } } #endif @@ -351,8 +394,7 @@ static void ScalePlaneDown34_16(int src_width, int src_height, } #endif #if defined(HAS_SCALEROWDOWN34_16_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { + if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3; ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3; @@ -435,28 +477,47 @@ static void ScalePlaneDown38(int src_width, int src_height, ScaleRowDown38_3 = ScaleRowDown38_3_Box_C; ScaleRowDown38_2 = ScaleRowDown38_2_Box_C; } + #if defined(HAS_SCALEROWDOWN38_NEON) - if (TestCpuFlag(kCpuHasNEON) && (dst_width % 12 == 0)) { + if (TestCpuFlag(kCpuHasNEON)) { if (!filtering) { - ScaleRowDown38_3 = ScaleRowDown38_NEON; - ScaleRowDown38_2 = ScaleRowDown38_NEON; + ScaleRowDown38_3 = ScaleRowDown38_Any_NEON; + ScaleRowDown38_2 = ScaleRowDown38_Any_NEON; } else { - ScaleRowDown38_3 = ScaleRowDown38_3_Box_NEON; - ScaleRowDown38_2 = ScaleRowDown38_2_Box_NEON; + ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_NEON; + ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_NEON; + } + if (dst_width % 12 == 0) { + if (!filtering) { + ScaleRowDown38_3 = ScaleRowDown38_NEON; + ScaleRowDown38_2 = ScaleRowDown38_NEON; + } else { + ScaleRowDown38_3 = ScaleRowDown38_3_Box_NEON; + ScaleRowDown38_2 = ScaleRowDown38_2_Box_NEON; + } } } -#elif defined(HAS_SCALEROWDOWN38_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { +#endif +#if defined(HAS_SCALEROWDOWN38_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3)) { if (!filtering) { + ScaleRowDown38_3 = ScaleRowDown38_Any_SSSE3; + ScaleRowDown38_2 = ScaleRowDown38_Any_SSSE3; + } else { + ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_SSSE3; + ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_SSSE3; + } + if (dst_width % 12 == 0 && !filtering) { ScaleRowDown38_3 = ScaleRowDown38_SSSE3; ScaleRowDown38_2 = ScaleRowDown38_SSSE3; - } else { + } + if (dst_width % 6 == 0 && filtering) { ScaleRowDown38_3 = ScaleRowDown38_3_Box_SSSE3; ScaleRowDown38_2 = ScaleRowDown38_2_Box_SSSE3; } } -#elif defined(HAS_SCALEROWDOWN38_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN38_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 12 == 0) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -522,9 +583,9 @@ static void ScalePlaneDown38_16(int src_width, int src_height, ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_NEON; } } -#elif defined(HAS_SCALEROWDOWN38_16_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { +#endif +#if defined(HAS_SCALEROWDOWN38_16_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) { if (!filtering) { ScaleRowDown38_3 = ScaleRowDown38_16_SSSE3; ScaleRowDown38_2 = ScaleRowDown38_16_SSSE3; @@ -533,7 +594,8 @@ static void ScalePlaneDown38_16(int src_width, int src_height, ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_SSSE3; } } -#elif defined(HAS_SCALEROWDOWN38_16_MIPS_DSPR2) +#endif +#if defined(HAS_SCALEROWDOWN38_16_MIPS_DSPR2) if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 12 == 0) && IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) { @@ -570,65 +632,7 @@ static void ScalePlaneDown38_16(int src_width, int src_height, } } -static __inline uint32 SumBox(int iboxwidth, int iboxheight, - ptrdiff_t src_stride, const uint8* src_ptr) { - uint32 sum = 0u; - int y; - assert(iboxwidth > 0); - assert(iboxheight > 0); - for (y = 0; y < iboxheight; ++y) { - int x; - for (x = 0; x < iboxwidth; ++x) { - sum += src_ptr[x]; - } - src_ptr += src_stride; - } - return sum; -} - -static __inline uint32 SumBox_16(int iboxwidth, int iboxheight, - ptrdiff_t src_stride, const uint16* src_ptr) { - uint32 sum = 0u; - int y; - assert(iboxwidth > 0); - assert(iboxheight > 0); - for (y = 0; y < iboxheight; ++y) { - int x; - for (x = 0; x < iboxwidth; ++x) { - sum += src_ptr[x]; - } - src_ptr += src_stride; - } - return sum; -} - -static void ScalePlaneBoxRow_C(int dst_width, int boxheight, - int x, int dx, ptrdiff_t src_stride, - const uint8* src_ptr, uint8* dst_ptr) { - int i; - int boxwidth; - for (i = 0; i < dst_width; ++i) { - int ix = x >> 16; - x += dx; - boxwidth = (x >> 16) - ix; - *dst_ptr++ = SumBox(boxwidth, boxheight, src_stride, src_ptr + ix) / - (boxwidth * boxheight); - } -} - -static void ScalePlaneBoxRow_16_C(int dst_width, int boxheight, - int x, int dx, ptrdiff_t src_stride, - const uint16* src_ptr, uint16* dst_ptr) { - int i; - int boxwidth; - for (i = 0; i < dst_width; ++i) { - int ix = x >> 16; - x += dx; - boxwidth = (x >> 16) - ix; - *dst_ptr++ = SumBox_16(boxwidth, boxheight, src_stride, src_ptr + ix) / - (boxwidth * boxheight); - } -} +#define MIN1(x) ((x) < 1 ? 1 : (x)) static __inline uint32 SumPixels(int iboxwidth, const uint16* src_ptr) { uint32 sum = 0u; @@ -654,15 +658,15 @@ static void ScaleAddCols2_C(int dst_width, int boxheight, int x, int dx, const uint16* src_ptr, uint8* dst_ptr) { int i; int scaletbl[2]; - int minboxwidth = (dx >> 16); + int minboxwidth = dx >> 16; int* scaleptr = scaletbl - minboxwidth; int boxwidth; - scaletbl[0] = 65536 / (minboxwidth * boxheight); - scaletbl[1] = 65536 / ((minboxwidth + 1) * boxheight); + scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight); + scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight); for (i = 0; i < dst_width; ++i) { int ix = x >> 16; x += dx; - boxwidth = (x >> 16) - ix; + boxwidth = MIN1((x >> 16) - ix); *dst_ptr++ = SumPixels(boxwidth, src_ptr + ix) * scaleptr[boxwidth] >> 16; } } @@ -671,25 +675,36 @@ static void ScaleAddCols2_16_C(int dst_width, int boxheight, int x, int dx, const uint32* src_ptr, uint16* dst_ptr) { int i; int scaletbl[2]; - int minboxwidth = (dx >> 16); + int minboxwidth = dx >> 16; int* scaleptr = scaletbl - minboxwidth; int boxwidth; - scaletbl[0] = 65536 / (minboxwidth * boxheight); - scaletbl[1] = 65536 / ((minboxwidth + 1) * boxheight); + scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight); + scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight); for (i = 0; i < dst_width; ++i) { int ix = x >> 16; x += dx; - boxwidth = (x >> 16) - ix; - *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + ix) * - scaleptr[boxwidth] >> 16; + boxwidth = MIN1((x >> 16) - ix); + *dst_ptr++ = + SumPixels_16(boxwidth, src_ptr + ix) * scaleptr[boxwidth] >> 16; + } +} + +static void ScaleAddCols0_C(int dst_width, int boxheight, int x, int, + const uint16* src_ptr, uint8* dst_ptr) { + int scaleval = 65536 / boxheight; + int i; + src_ptr += (x >> 16); + for (i = 0; i < dst_width; ++i) { + *dst_ptr++ = src_ptr[i] * scaleval >> 16; } } static void ScaleAddCols1_C(int dst_width, int boxheight, int x, int dx, const uint16* src_ptr, uint8* dst_ptr) { - int boxwidth = (dx >> 16); + int boxwidth = MIN1(dx >> 16); int scaleval = 65536 / (boxwidth * boxheight); int i; + x >>= 16; for (i = 0; i < dst_width; ++i) { *dst_ptr++ = SumPixels(boxwidth, src_ptr + x) * scaleval >> 16; x += boxwidth; @@ -698,7 +713,7 @@ static void ScaleAddCols1_C(int dst_width, int boxheight, int x, int dx, static void ScaleAddCols1_16_C(int dst_width, int boxheight, int x, int dx, const uint32* src_ptr, uint16* dst_ptr) { - int boxwidth = (dx >> 16); + int boxwidth = MIN1(dx >> 16); int scaleval = 65536 / (boxwidth * boxheight); int i; for (i = 0; i < dst_width; ++i) { @@ -718,7 +733,7 @@ static void ScalePlaneBox(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint8* src_ptr, uint8* dst_ptr) { - int j; + int j, k; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; int y = 0; @@ -728,10 +743,40 @@ static void ScalePlaneBox(int src_width, int src_height, ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y, &dx, &dy); src_width = Abs(src_width); - // TODO(fbarchard): Remove this and make AddRows handle boxheight 1. - if (!IS_ALIGNED(src_width, 16) || dst_height * 2 > src_height) { - uint8* dst = dst_ptr; - int j; + { + // Allocate a row buffer of uint16. + align_buffer_64(row16, src_width * 2); + void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx, + const uint16* src_ptr, uint8* dst_ptr) = + (dx & 0xffff) ? ScaleAddCols2_C: + ((dx != 0x10000) ? ScaleAddCols1_C : ScaleAddCols0_C); + void (*ScaleAddRow)(const uint8* src_ptr, uint16* dst_ptr, int src_width) = + ScaleAddRow_C; +#if defined(HAS_SCALEADDROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2)) { + ScaleAddRow = ScaleAddRow_Any_SSE2; + if (IS_ALIGNED(src_width, 16)) { + ScaleAddRow = ScaleAddRow_SSE2; + } + } +#endif +#if defined(HAS_SCALEADDROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2)) { + ScaleAddRow = ScaleAddRow_Any_AVX2; + if (IS_ALIGNED(src_width, 32)) { + ScaleAddRow = ScaleAddRow_AVX2; + } + } +#endif +#if defined(HAS_SCALEADDROW_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleAddRow = ScaleAddRow_Any_NEON; + if (IS_ALIGNED(src_width, 16)) { + ScaleAddRow = ScaleAddRow_NEON; + } + } +#endif + for (j = 0; j < dst_height; ++j) { int boxheight; int iy = y >> 16; @@ -740,46 +785,13 @@ static void ScalePlaneBox(int src_width, int src_height, if (y > max_y) { y = max_y; } - boxheight = (y >> 16) - iy; - ScalePlaneBoxRow_C(dst_width, boxheight, - x, dx, src_stride, - src, dst); - dst += dst_stride; - } - return; - } - { - // Allocate a row buffer of uint16. - align_buffer_64(row16, src_width * 2); - void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx, - const uint16* src_ptr, uint8* dst_ptr) = - (dx & 0xffff) ? ScaleAddCols2_C: ScaleAddCols1_C; - void (*ScaleAddRows)(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, int src_height) = ScaleAddRows_C; - -#if defined(HAS_SCALEADDROWS_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && -#ifdef AVOID_OVERREAD - IS_ALIGNED(src_width, 16) && -#endif - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - ScaleAddRows = ScaleAddRows_SSE2; - } -#endif - - for (j = 0; j < dst_height; ++j) { - int boxheight; - int iy = y >> 16; - const uint8* src = src_ptr + iy * src_stride; - y += dy; - if (y > (src_height << 16)) { - y = (src_height << 16); + boxheight = MIN1((y >> 16) - iy); + memset(row16, 0, src_width * 2); + for (k = 0; k < boxheight; ++k) { + ScaleAddRow(src, (uint16 *)(row16), src_width); + src += src_stride; } - boxheight = (y >> 16) - iy; - ScaleAddRows(src, src_stride, (uint16*)(row16), - src_width, boxheight); - ScaleAddCols(dst_width, boxheight, x, dx, (uint16*)(row16), - dst_ptr); + ScaleAddCols(dst_width, boxheight, x, dx, (uint16*)(row16), dst_ptr); dst_ptr += dst_stride; } free_aligned_buffer_64(row16); @@ -790,7 +802,7 @@ static void ScalePlaneBox_16(int src_width, int src_height, int dst_width, int dst_height, int src_stride, int dst_stride, const uint16* src_ptr, uint16* dst_ptr) { - int j; + int j, k; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; int y = 0; @@ -800,10 +812,21 @@ static void ScalePlaneBox_16(int src_width, int src_height, ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y, &dx, &dy); src_width = Abs(src_width); - // TODO(fbarchard): Remove this and make AddRows handle boxheight 1. - if (!IS_ALIGNED(src_width, 16) || dst_height * 2 > src_height) { - uint16* dst = dst_ptr; - int j; + { + // Allocate a row buffer of uint32. + align_buffer_64(row32, src_width * 4); + void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx, + const uint32* src_ptr, uint16* dst_ptr) = + (dx & 0xffff) ? ScaleAddCols2_16_C: ScaleAddCols1_16_C; + void (*ScaleAddRow)(const uint16* src_ptr, uint32* dst_ptr, int src_width) = + ScaleAddRow_16_C; + +#if defined(HAS_SCALEADDROW_16_SSE2) + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(src_width, 16)) { + ScaleAddRow = ScaleAddRow_16_SSE2; + } +#endif + for (j = 0; j < dst_height; ++j) { int boxheight; int iy = y >> 16; @@ -812,46 +835,13 @@ static void ScalePlaneBox_16(int src_width, int src_height, if (y > max_y) { y = max_y; } - boxheight = (y >> 16) - iy; - ScalePlaneBoxRow_16_C(dst_width, boxheight, - x, dx, src_stride, - src, dst); - dst += dst_stride; - } - return; - } - { - // Allocate a row buffer of uint32. - align_buffer_64(row32, src_width * 4); - void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx, - const uint32* src_ptr, uint16* dst_ptr) = - (dx & 0xffff) ? ScaleAddCols2_16_C: ScaleAddCols1_16_C; - void (*ScaleAddRows)(const uint16* src_ptr, ptrdiff_t src_stride, - uint32* dst_ptr, int src_width, int src_height) = ScaleAddRows_16_C; - -#if defined(HAS_SCALEADDROWS_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && -#ifdef AVOID_OVERREAD - IS_ALIGNED(src_width, 16) && -#endif - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - ScaleAddRows = ScaleAddRows_16_SSE2; - } -#endif - - for (j = 0; j < dst_height; ++j) { - int boxheight; - int iy = y >> 16; - const uint16* src = src_ptr + iy * src_stride; - y += dy; - if (y > (src_height << 16)) { - y = (src_height << 16); + boxheight = MIN1((y >> 16) - iy); + memset(row32, 0, src_width * 4); + for (k = 0; k < boxheight; ++k) { + ScaleAddRow(src, (uint32 *)(row32), src_width); + src += src_stride; } - boxheight = (y >> 16) - iy; - ScaleAddRows(src, src_stride, (uint32*)(row32), - src_width, boxheight); - ScaleAddCols(dst_width, boxheight, x, dx, (uint32*)(row32), - dst_ptr); + ScaleAddCols(dst_width, boxheight, x, dx, (uint32*)(row32), dst_ptr); dst_ptr += dst_stride; } free_aligned_buffer_64(row32); @@ -885,30 +875,16 @@ void ScalePlaneBilinearDown(int src_width, int src_height, &x, &y, &dx, &dy); src_width = Abs(src_width); -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && src_width >= 16) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && src_width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(src_width, 32)) { InterpolateRow = InterpolateRow_AVX2; @@ -916,7 +892,7 @@ void ScalePlaneBilinearDown(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && src_width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(src_width, 16)) { InterpolateRow = InterpolateRow_NEON; @@ -924,7 +900,7 @@ void ScalePlaneBilinearDown(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && src_width >= 4) { + if (TestCpuFlag(kCpuHasMIPS_DSPR2)) { InterpolateRow = InterpolateRow_Any_MIPS_DSPR2; if (IS_ALIGNED(src_width, 4)) { InterpolateRow = InterpolateRow_MIPS_DSPR2; @@ -937,6 +913,14 @@ void ScalePlaneBilinearDown(int src_width, int src_height, if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) { ScaleFilterCols = ScaleFilterCols_SSSE3; } +#endif +#if defined(HAS_SCALEFILTERCOLS_NEON) + if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) { + ScaleFilterCols = ScaleFilterCols_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleFilterCols = ScaleFilterCols_NEON; + } + } #endif if (y > max_y) { y = max_y; @@ -988,29 +972,23 @@ void ScalePlaneBilinearDown_16(int src_width, int src_height, src_width = Abs(src_width); #if defined(HAS_INTERPOLATEROW_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && src_width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { InterpolateRow = InterpolateRow_Any_16_SSE2; if (IS_ALIGNED(src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSE2; - if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSE2; - } + InterpolateRow = InterpolateRow_16_SSE2; } } #endif #if defined(HAS_INTERPOLATEROW_16_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_16_SSSE3; if (IS_ALIGNED(src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSSE3; - if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSSE3; - } + InterpolateRow = InterpolateRow_16_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_16_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && src_width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_16_AVX2; if (IS_ALIGNED(src_width, 32)) { InterpolateRow = InterpolateRow_16_AVX2; @@ -1018,7 +996,7 @@ void ScalePlaneBilinearDown_16(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_16_NEON) - if (TestCpuFlag(kCpuHasNEON) && src_width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_16_NEON; if (IS_ALIGNED(src_width, 16)) { InterpolateRow = InterpolateRow_16_NEON; @@ -1026,7 +1004,7 @@ void ScalePlaneBilinearDown_16(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_16_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && src_width >= 4) { + if (TestCpuFlag(kCpuHasMIPS_DSPR2)) { InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2; if (IS_ALIGNED(src_width, 4)) { InterpolateRow = InterpolateRow_16_MIPS_DSPR2; @@ -1080,36 +1058,22 @@ void ScalePlaneBilinearUp(int src_width, int src_height, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_C; void (*ScaleFilterCols)(uint8* dst_ptr, const uint8* src_ptr, - int dst_width, int x, int dx) = - filtering ? ScaleFilterCols_C : ScaleCols_C; + int dst_width, int x, int dx) = + filtering ? ScaleFilterCols_C : ScaleCols_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, &dx, &dy); src_width = Abs(src_width); -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 16) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(dst_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(dst_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(dst_width, 32)) { InterpolateRow = InterpolateRow_AVX2; @@ -1117,7 +1081,7 @@ void ScalePlaneBilinearUp(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(dst_width, 16)) { InterpolateRow = InterpolateRow_NEON; @@ -1125,7 +1089,7 @@ void ScalePlaneBilinearUp(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasMIPS_DSPR2)) { InterpolateRow = InterpolateRow_Any_MIPS_DSPR2; if (IS_ALIGNED(dst_width, 4)) { InterpolateRow = InterpolateRow_MIPS_DSPR2; @@ -1140,13 +1104,19 @@ void ScalePlaneBilinearUp(int src_width, int src_height, if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) { ScaleFilterCols = ScaleFilterCols_SSSE3; } +#endif +#if defined(HAS_SCALEFILTERCOLS_NEON) + if (filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) { + ScaleFilterCols = ScaleFilterCols_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleFilterCols = ScaleFilterCols_NEON; + } + } #endif if (!filtering && src_width * 2 == dst_width && x < 0x8000) { ScaleFilterCols = ScaleColsUp2_C; #if defined(HAS_SCALECOLS_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleFilterCols = ScaleColsUp2_SSE2; } #endif @@ -1160,7 +1130,7 @@ void ScalePlaneBilinearUp(int src_width, int src_height, const uint8* src = src_ptr + yi * src_stride; // Allocate 2 row buffers. - const int kRowSize = (dst_width + 15) & ~15; + const int kRowSize = (dst_width + 31) & ~31; align_buffer_64(row, kRowSize * 2); uint8* rowptr = row; @@ -1219,36 +1189,30 @@ void ScalePlaneBilinearUp_16(int src_width, int src_height, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_16_C; void (*ScaleFilterCols)(uint16* dst_ptr, const uint16* src_ptr, - int dst_width, int x, int dx) = - filtering ? ScaleFilterCols_16_C : ScaleCols_16_C; + int dst_width, int x, int dx) = + filtering ? ScaleFilterCols_16_C : ScaleCols_16_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, &dx, &dy); src_width = Abs(src_width); #if defined(HAS_INTERPOLATEROW_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { InterpolateRow = InterpolateRow_Any_16_SSE2; if (IS_ALIGNED(dst_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSE2; - if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSE2; - } + InterpolateRow = InterpolateRow_16_SSE2; } } #endif #if defined(HAS_INTERPOLATEROW_16_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_16_SSSE3; if (IS_ALIGNED(dst_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSSE3; - if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSSE3; - } + InterpolateRow = InterpolateRow_16_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_16_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_16_AVX2; if (IS_ALIGNED(dst_width, 32)) { InterpolateRow = InterpolateRow_16_AVX2; @@ -1256,7 +1220,7 @@ void ScalePlaneBilinearUp_16(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_16_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_16_NEON; if (IS_ALIGNED(dst_width, 16)) { InterpolateRow = InterpolateRow_16_NEON; @@ -1264,7 +1228,7 @@ void ScalePlaneBilinearUp_16(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_16_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasMIPS_DSPR2)) { InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2; if (IS_ALIGNED(dst_width, 4)) { InterpolateRow = InterpolateRow_16_MIPS_DSPR2; @@ -1283,9 +1247,7 @@ void ScalePlaneBilinearUp_16(int src_width, int src_height, if (!filtering && src_width * 2 == dst_width && x < 0x8000) { ScaleFilterCols = ScaleColsUp2_16_C; #if defined(HAS_SCALECOLS_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleFilterCols = ScaleColsUp2_16_SSE2; } #endif @@ -1299,7 +1261,7 @@ void ScalePlaneBilinearUp_16(int src_width, int src_height, const uint16* src = src_ptr + yi * src_stride; // Allocate 2 row buffers. - const int kRowSize = (dst_width + 15) & ~15; + const int kRowSize = (dst_width + 31) & ~31; align_buffer_64(row, kRowSize * 4); uint16* rowptr = (uint16*)row; @@ -1366,17 +1328,14 @@ static void ScalePlaneSimple(int src_width, int src_height, if (src_width * 2 == dst_width && x < 0x8000) { ScaleCols = ScaleColsUp2_C; #if defined(HAS_SCALECOLS_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleCols = ScaleColsUp2_SSE2; } #endif } for (i = 0; i < dst_height; ++i) { - ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride, - dst_width, x, dx); + ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride, dst_width, x, dx); dst_ptr += dst_stride; y += dy; } @@ -1401,9 +1360,7 @@ static void ScalePlaneSimple_16(int src_width, int src_height, if (src_width * 2 == dst_width && x < 0x8000) { ScaleCols = ScaleColsUp2_16_C; #if defined(HAS_SCALECOLS_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleCols = ScaleColsUp2_16_SSE2; } #endif @@ -1428,8 +1385,7 @@ void ScalePlane(const uint8* src, int src_stride, enum FilterMode filtering) { // Simplify filtering when possible. filtering = ScaleFilterReduce(src_width, src_height, - dst_width, dst_height, - filtering); + dst_width, dst_height, filtering); // Negative height means invert the image. if (src_height < 0) { @@ -1445,9 +1401,9 @@ void ScalePlane(const uint8* src, int src_stride, CopyPlane(src, src_stride, dst, dst_stride, dst_width, dst_height); return; } - if (dst_width == src_width) { + if (dst_width == src_width && filtering != kFilterBox) { int dy = FixedDiv(src_height, dst_height); - // Arbitrary scale vertically, but unscaled vertically. + // Arbitrary scale vertically, but unscaled horizontally. ScalePlaneVertical(src_height, dst_width, dst_height, src_stride, dst_stride, src, dst, @@ -1478,7 +1434,7 @@ void ScalePlane(const uint8* src, int src_stride, return; } if (4 * dst_width == src_width && 4 * dst_height == src_height && - filtering != kFilterBilinear) { + (filtering == kFilterBox || filtering == kFilterNone)) { // optimized, 1/4 ScalePlaneDown4(src_width, src_height, dst_width, dst_height, src_stride, dst_stride, src, dst, filtering); @@ -1512,8 +1468,7 @@ void ScalePlane_16(const uint16* src, int src_stride, enum FilterMode filtering) { // Simplify filtering when possible. filtering = ScaleFilterReduce(src_width, src_height, - dst_width, dst_height, - filtering); + dst_width, dst_height, filtering); // Negative height means invert the image. if (src_height < 0) { @@ -1606,6 +1561,7 @@ int I420Scale(const uint8* src_y, int src_stride_y, int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1); int dst_halfheight = SUBSAMPLE(dst_height, 1, 1); if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 || + src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) { return -1; } @@ -1637,6 +1593,7 @@ int I420Scale_16(const uint16* src_y, int src_stride_y, int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1); int dst_halfheight = SUBSAMPLE(dst_height, 1, 1); if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 || + src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) { return -1; } diff --git a/TMessagesProj/jni/libyuv/source/scale_argb.cc b/TMessagesProj/jni/libyuv/source/scale_argb.cc index e339cd7c..adddf9db 100644 --- a/TMessagesProj/jni/libyuv/source/scale_argb.cc +++ b/TMessagesProj/jni/libyuv/source/scale_argb.cc @@ -53,18 +53,27 @@ static void ScaleARGBDown2(int src_width, int src_height, } #if defined(HAS_SCALEARGBROWDOWN2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_SSE2 : - (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_SSE2 : - ScaleARGBRowDown2Box_SSE2); + if (TestCpuFlag(kCpuHasSSE2)) { + ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_Any_SSE2 : + (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_Any_SSE2 : + ScaleARGBRowDown2Box_Any_SSE2); + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_SSE2 : + (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_SSE2 : + ScaleARGBRowDown2Box_SSE2); + } } -#elif defined(HAS_SCALEARGBROWDOWN2_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_argb, 4) && IS_ALIGNED(row_stride, 4)) { - ScaleARGBRowDown2 = filtering ? ScaleARGBRowDown2Box_NEON : - ScaleARGBRowDown2_NEON; +#endif +#if defined(HAS_SCALEARGBROWDOWN2_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_Any_NEON : + (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_Any_NEON : + ScaleARGBRowDown2Box_Any_NEON); + if (IS_ALIGNED(dst_width, 8)) { + ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_NEON : + (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_NEON : + ScaleARGBRowDown2Box_NEON); + } } #endif @@ -88,7 +97,7 @@ static void ScaleARGBDown4Box(int src_width, int src_height, int x, int dx, int y, int dy) { int j; // Allocate 2 rows of ARGB. - const int kRowSize = (dst_width * 2 * 4 + 15) & ~15; + const int kRowSize = (dst_width * 2 * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); int row_stride = src_stride * (dy >> 16); void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride, @@ -98,17 +107,22 @@ static void ScaleARGBDown4Box(int src_width, int src_height, assert(dx == 65536 * 4); // Test scale factor of 4. assert((dy & 0x3ffff) == 0); // Test vertical scale is multiple of 4. #if defined(HAS_SCALEARGBROWDOWN2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(row_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - ScaleARGBRowDown2 = ScaleARGBRowDown2Box_SSE2; - } -#elif defined(HAS_SCALEARGBROWDOWN2_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_argb, 4) && IS_ALIGNED(row_stride, 4)) { - ScaleARGBRowDown2 = ScaleARGBRowDown2Box_NEON; + if (TestCpuFlag(kCpuHasSSE2)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_Any_SSE2; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_SSE2; + } } #endif +#if defined(HAS_SCALEARGBROWDOWN2_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleARGBRowDown2 = ScaleARGBRowDown2Box_NEON; + } + } +#endif + for (j = 0; j < dst_height; ++j) { ScaleARGBRowDown2(src_argb, src_stride, row, dst_width * 2); ScaleARGBRowDown2(src_argb + src_stride * 2, src_stride, @@ -139,16 +153,23 @@ static void ScaleARGBDownEven(int src_width, int src_height, assert(IS_ALIGNED(src_height, 2)); src_argb += (y >> 16) * src_stride + (x >> 16) * 4; #if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_SSE2 : - ScaleARGBRowDownEven_SSE2; + if (TestCpuFlag(kCpuHasSSE2)) { + ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_Any_SSE2 : + ScaleARGBRowDownEven_Any_SSE2; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_SSE2 : + ScaleARGBRowDownEven_SSE2; + } } -#elif defined(HAS_SCALEARGBROWDOWNEVEN_NEON) - if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 4) && - IS_ALIGNED(src_argb, 4)) { - ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_NEON : - ScaleARGBRowDownEven_NEON; +#endif +#if defined(HAS_SCALEARGBROWDOWNEVEN_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_Any_NEON : + ScaleARGBRowDownEven_Any_NEON; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_NEON : + ScaleARGBRowDownEven_NEON; + } } #endif @@ -189,30 +210,16 @@ static void ScaleARGBBilinearDown(int src_width, int src_height, clip_src_width = (int)(xr - xl) * 4; // Width aligned to 4. src_argb += xl * 4; x -= (int)(xl << 16); -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && clip_src_width >= 16) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(clip_src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && clip_src_width >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(clip_src_width, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && clip_src_width >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(clip_src_width, 32)) { InterpolateRow = InterpolateRow_AVX2; @@ -220,15 +227,15 @@ static void ScaleARGBBilinearDown(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && clip_src_width >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(clip_src_width, 16)) { InterpolateRow = InterpolateRow_NEON; } } #endif -#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && clip_src_width >= 4 && +#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4)) { InterpolateRow = InterpolateRow_Any_MIPS_DSPR2; if (IS_ALIGNED(clip_src_width, 4)) { @@ -240,6 +247,14 @@ static void ScaleARGBBilinearDown(int src_width, int src_height, if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3; } +#endif +#if defined(HAS_SCALEARGBFILTERCOLS_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_NEON; + } + } #endif // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear. // Allocate a row of ARGB. @@ -285,30 +300,16 @@ static void ScaleARGBBilinearUp(int src_width, int src_height, int dst_width, int x, int dx) = filtering ? ScaleARGBFilterCols_C : ScaleARGBCols_C; const int max_y = (src_height - 1) << 16; -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 4) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(dst_width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(dst_width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(dst_width, 8)) { InterpolateRow = InterpolateRow_AVX2; @@ -316,15 +317,15 @@ static void ScaleARGBBilinearUp(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(dst_width, 4)) { InterpolateRow = InterpolateRow_NEON; } } #endif -#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 1 && +#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) { InterpolateRow = InterpolateRow_MIPS_DSPR2; } @@ -338,17 +339,31 @@ static void ScaleARGBBilinearUp(int src_width, int src_height, ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3; } #endif +#if defined(HAS_SCALEARGBFILTERCOLS_NEON) + if (filtering && TestCpuFlag(kCpuHasNEON)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_NEON; + } + } +#endif #if defined(HAS_SCALEARGBCOLS_SSE2) if (!filtering && TestCpuFlag(kCpuHasSSE2) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBCols_SSE2; } +#endif +#if defined(HAS_SCALEARGBCOLS_NEON) + if (!filtering && TestCpuFlag(kCpuHasNEON)) { + ScaleARGBFilterCols = ScaleARGBCols_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleARGBFilterCols = ScaleARGBCols_NEON; + } + } #endif if (!filtering && src_width * 2 == dst_width && x < 0x8000) { ScaleARGBFilterCols = ScaleARGBColsUp2_C; #if defined(HAS_SCALEARGBCOLSUP2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleARGBFilterCols = ScaleARGBColsUp2_SSE2; } #endif @@ -363,7 +378,7 @@ static void ScaleARGBBilinearUp(int src_width, int src_height, const uint8* src = src_argb + yi * src_stride; // Allocate 2 rows of ARGB. - const int kRowSize = (dst_width * 4 + 15) & ~15; + const int kRowSize = (dst_width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); uint8* rowptr = row; @@ -427,18 +442,15 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, uint8* rgb_buf, int width) = I422ToARGBRow_C; #if defined(HAS_I422TOARGBROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 8) { + if (TestCpuFlag(kCpuHasSSSE3)) { I422ToARGBRow = I422ToARGBRow_Any_SSSE3; if (IS_ALIGNED(src_width, 8)) { - I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - I422ToARGBRow = I422ToARGBRow_SSSE3; - } + I422ToARGBRow = I422ToARGBRow_SSSE3; } } #endif #if defined(HAS_I422TOARGBROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && src_width >= 16) { + if (TestCpuFlag(kCpuHasAVX2)) { I422ToARGBRow = I422ToARGBRow_Any_AVX2; if (IS_ALIGNED(src_width, 16)) { I422ToARGBRow = I422ToARGBRow_AVX2; @@ -446,7 +458,7 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, } #endif #if defined(HAS_I422TOARGBROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && src_width >= 8) { + if (TestCpuFlag(kCpuHasNEON)) { I422ToARGBRow = I422ToARGBRow_Any_NEON; if (IS_ALIGNED(src_width, 8)) { I422ToARGBRow = I422ToARGBRow_NEON; @@ -466,30 +478,16 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb, ptrdiff_t src_stride, int dst_width, int source_y_fraction) = InterpolateRow_C; -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 4) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(dst_width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(dst_width, 4)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 8) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(dst_width, 8)) { InterpolateRow = InterpolateRow_AVX2; @@ -497,15 +495,15 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width >= 4) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(dst_width, 4)) { InterpolateRow = InterpolateRow_NEON; } } #endif -#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 1 && +#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { InterpolateRow = InterpolateRow_MIPS_DSPR2; } @@ -523,17 +521,31 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3; } #endif +#if defined(HAS_SCALEARGBFILTERCOLS_NEON) + if (filtering && TestCpuFlag(kCpuHasNEON)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON; + if (IS_ALIGNED(dst_width, 4)) { + ScaleARGBFilterCols = ScaleARGBFilterCols_NEON; + } + } +#endif #if defined(HAS_SCALEARGBCOLS_SSE2) if (!filtering && TestCpuFlag(kCpuHasSSE2) && src_width < 32768) { ScaleARGBFilterCols = ScaleARGBCols_SSE2; } +#endif +#if defined(HAS_SCALEARGBCOLS_NEON) + if (!filtering && TestCpuFlag(kCpuHasNEON)) { + ScaleARGBFilterCols = ScaleARGBCols_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleARGBFilterCols = ScaleARGBCols_NEON; + } + } #endif if (!filtering && src_width * 2 == dst_width && x < 0x8000) { ScaleARGBFilterCols = ScaleARGBColsUp2_C; #if defined(HAS_SCALEARGBCOLSUP2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleARGBFilterCols = ScaleARGBColsUp2_SSE2; } #endif @@ -551,7 +563,7 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height, const uint8* src_row_v = src_v + uv_yi * src_stride_v; // Allocate 2 rows of ARGB. - const int kRowSize = (dst_width * 4 + 15) & ~15; + const int kRowSize = (dst_width * 4 + 31) & ~31; align_buffer_64(row, kRowSize * 2); // Allocate 1 row of ARGB for source conversion. @@ -636,13 +648,19 @@ static void ScaleARGBSimple(int src_width, int src_height, if (TestCpuFlag(kCpuHasSSE2) && src_width < 32768) { ScaleARGBCols = ScaleARGBCols_SSE2; } +#endif +#if defined(HAS_SCALEARGBCOLS_NEON) + if (TestCpuFlag(kCpuHasNEON)) { + ScaleARGBCols = ScaleARGBCols_Any_NEON; + if (IS_ALIGNED(dst_width, 8)) { + ScaleARGBCols = ScaleARGBCols_NEON; + } + } #endif if (src_width * 2 == dst_width && x < 0x8000) { ScaleARGBCols = ScaleARGBColsUp2_C; #if defined(HAS_SCALEARGBCOLSUP2_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) && - IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { ScaleARGBCols = ScaleARGBColsUp2_SSE2; } #endif @@ -776,6 +794,7 @@ int ARGBScaleClip(const uint8* src_argb, int src_stride_argb, if (!src_argb || src_width == 0 || src_height == 0 || !dst_argb || dst_width <= 0 || dst_height <= 0 || clip_x < 0 || clip_y < 0 || + clip_width > 32768 || clip_height > 32768 || (clip_x + clip_width) > dst_width || (clip_y + clip_height) > dst_height) { return -1; @@ -794,6 +813,7 @@ int ARGBScale(const uint8* src_argb, int src_stride_argb, int dst_width, int dst_height, enum FilterMode filtering) { if (!src_argb || src_width == 0 || src_height == 0 || + src_width > 32768 || src_height > 32768 || !dst_argb || dst_width <= 0 || dst_height <= 0) { return -1; } @@ -803,6 +823,37 @@ int ARGBScale(const uint8* src_argb, int src_stride_argb, return 0; } +// Scale with YUV conversion to ARGB and clipping. +LIBYUV_API +int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint32 src_fourcc, + int src_width, int src_height, + uint8* dst_argb, int dst_stride_argb, + uint32 dst_fourcc, + int dst_width, int dst_height, + int clip_x, int clip_y, int clip_width, int clip_height, + enum FilterMode filtering) { + + uint8* argb_buffer = (uint8*)malloc(src_width * src_height * 4); + int r; + I420ToARGB(src_y, src_stride_y, + src_u, src_stride_u, + src_v, src_stride_v, + argb_buffer, src_width * 4, + src_width, src_height); + + r = ARGBScaleClip(argb_buffer, src_width * 4, + src_width, src_height, + dst_argb, dst_stride_argb, + dst_width, dst_height, + clip_x, clip_y, clip_width, clip_height, + filtering); + free(argb_buffer); + return r; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/TMessagesProj/jni/libyuv/source/scale_common.cc b/TMessagesProj/jni/libyuv/source/scale_common.cc index e4b2acc4..f5c908d0 100644 --- a/TMessagesProj/jni/libyuv/source/scale_common.cc +++ b/TMessagesProj/jni/libyuv/source/scale_common.cc @@ -621,39 +621,31 @@ void ScaleRowDown38_2_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride, } } -void ScaleAddRows_C(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, int src_height) { +void ScaleAddRow_C(const uint8* src_ptr, uint16* dst_ptr, int src_width) { int x; assert(src_width > 0); - assert(src_height > 0); - for (x = 0; x < src_width; ++x) { - const uint8* s = src_ptr + x; - unsigned int sum = 0u; - int y; - for (y = 0; y < src_height; ++y) { - sum += s[0]; - s += src_stride; - } - // TODO(fbarchard): Consider limitting height to 256 to avoid overflow. - dst_ptr[x] = sum < 65535u ? sum : 65535u; + for (x = 0; x < src_width - 1; x += 2) { + dst_ptr[0] += src_ptr[0]; + dst_ptr[1] += src_ptr[1]; + src_ptr += 2; + dst_ptr += 2; + } + if (src_width & 1) { + dst_ptr[0] += src_ptr[0]; } } -void ScaleAddRows_16_C(const uint16* src_ptr, ptrdiff_t src_stride, - uint32* dst_ptr, int src_width, int src_height) { +void ScaleAddRow_16_C(const uint16* src_ptr, uint32* dst_ptr, int src_width) { int x; assert(src_width > 0); - assert(src_height > 0); - for (x = 0; x < src_width; ++x) { - const uint16* s = src_ptr + x; - unsigned int sum = 0u; - int y; - for (y = 0; y < src_height; ++y) { - sum += s[0]; - s += src_stride; - } - // No risk of overflow here now - dst_ptr[x] = sum; + for (x = 0; x < src_width - 1; x += 2) { + dst_ptr[0] += src_ptr[0]; + dst_ptr[1] += src_ptr[1]; + src_ptr += 2; + dst_ptr += 2; + } + if (src_width & 1) { + dst_ptr[0] += src_ptr[0]; } } @@ -884,32 +876,16 @@ void ScalePlaneVertical(int src_height, assert(dst_width > 0); assert(dst_height > 0); src_argb += (x >> 16) * bpp; -#if defined(HAS_INTERPOLATEROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width_bytes >= 16) { - InterpolateRow = InterpolateRow_Any_SSE2; - if (IS_ALIGNED(dst_width_bytes, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSE2; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSE2; - } - } - } -#endif #if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width_bytes >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_SSSE3; if (IS_ALIGNED(dst_width_bytes, 16)) { - InterpolateRow = InterpolateRow_Unaligned_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } + InterpolateRow = InterpolateRow_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width_bytes >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_AVX2; if (IS_ALIGNED(dst_width_bytes, 32)) { InterpolateRow = InterpolateRow_AVX2; @@ -917,15 +893,15 @@ void ScalePlaneVertical(int src_height, } #endif #if defined(HAS_INTERPOLATEROW_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width_bytes >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_NEON; if (IS_ALIGNED(dst_width_bytes, 16)) { InterpolateRow = InterpolateRow_NEON; } } #endif -#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width_bytes >= 4 && +#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) { InterpolateRow = InterpolateRow_Any_MIPS_DSPR2; @@ -967,31 +943,23 @@ void ScalePlaneVertical_16(int src_height, assert(dst_height > 0); src_argb += (x >> 16) * wpp; #if defined(HAS_INTERPOLATEROW_16_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && dst_width_bytes >= 16) { + if (TestCpuFlag(kCpuHasSSE2)) { InterpolateRow = InterpolateRow_Any_16_SSE2; if (IS_ALIGNED(dst_width_bytes, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSE2; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSE2; - } + InterpolateRow = InterpolateRow_16_SSE2; } } #endif #if defined(HAS_INTERPOLATEROW_16_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && dst_width_bytes >= 16) { + if (TestCpuFlag(kCpuHasSSSE3)) { InterpolateRow = InterpolateRow_Any_16_SSSE3; if (IS_ALIGNED(dst_width_bytes, 16)) { - InterpolateRow = InterpolateRow_Unaligned_16_SSSE3; - if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && - IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { - InterpolateRow = InterpolateRow_16_SSSE3; - } + InterpolateRow = InterpolateRow_16_SSSE3; } } #endif #if defined(HAS_INTERPOLATEROW_16_AVX2) - if (TestCpuFlag(kCpuHasAVX2) && dst_width_bytes >= 32) { + if (TestCpuFlag(kCpuHasAVX2)) { InterpolateRow = InterpolateRow_Any_16_AVX2; if (IS_ALIGNED(dst_width_bytes, 32)) { InterpolateRow = InterpolateRow_16_AVX2; @@ -999,15 +967,15 @@ void ScalePlaneVertical_16(int src_height, } #endif #if defined(HAS_INTERPOLATEROW_16_NEON) - if (TestCpuFlag(kCpuHasNEON) && dst_width_bytes >= 16) { + if (TestCpuFlag(kCpuHasNEON)) { InterpolateRow = InterpolateRow_Any_16_NEON; if (IS_ALIGNED(dst_width_bytes, 16)) { InterpolateRow = InterpolateRow_16_NEON; } } #endif -#if defined(HAS_INTERPOLATEROWS_16_MIPS_DSPR2) - if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width_bytes >= 4 && +#if defined(HAS_INTERPOLATEROW_16_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) { InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2; @@ -1046,10 +1014,6 @@ enum FilterMode ScaleFilterReduce(int src_width, int src_height, if (dst_width * 2 >= src_width && dst_height * 2 >= src_height) { filtering = kFilterBilinear; } - // If scaling to larger, switch from Box to Bilinear. - if (dst_width >= src_width || dst_height >= src_height) { - filtering = kFilterBilinear; - } } if (filtering == kFilterBilinear) { if (src_height == 1) { diff --git a/TMessagesProj/jni/libyuv/source/scale_mips.cc b/TMessagesProj/jni/libyuv/source/scale_mips.cc index 3eb4f27c..2298a74b 100644 --- a/TMessagesProj/jni/libyuv/source/scale_mips.cc +++ b/TMessagesProj/jni/libyuv/source/scale_mips.cc @@ -31,7 +31,6 @@ void ScaleRowDown2_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, "beqz $t9, 2f \n" " nop \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t1, 4(%[src_ptr]) \n" // |7|6|5|4| @@ -90,7 +89,6 @@ void ScaleRowDown2Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, "bltz $t9, 2f \n" " nop \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t1, 4(%[src_ptr]) \n" // |7|6|5|4| @@ -188,7 +186,6 @@ void ScaleRowDown4_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, "beqz $t9, 2f \n" " nop \n" - ".p2align 2 \n" "1: \n" "lw $t1, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t2, 4(%[src_ptr]) \n" // |7|6|5|4| @@ -248,7 +245,6 @@ void ScaleRowDown4Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, "srl $t9, %[dst_width], 1 \n" "andi $t8, %[dst_width], 1 \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t1, 0(%[s1]) \n" // |7|6|5|4| @@ -319,7 +315,6 @@ void ScaleRowDown34_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, __asm__ __volatile__ ( ".set push \n" ".set noreorder \n" - ".p2align 2 \n" "1: \n" "lw $t1, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t2, 4(%[src_ptr]) \n" // |7|6|5|4| @@ -368,7 +363,6 @@ void ScaleRowDown34_0_Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, ".set noreorder \n" "repl.ph $t3, 3 \n" // 0x00030003 - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |S3|S2|S1|S0| "lwx $t1, %[src_stride](%[src_ptr]) \n" // |T3|T2|T1|T0| @@ -425,7 +419,6 @@ void ScaleRowDown34_1_Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, ".set noreorder \n" "repl.ph $t2, 3 \n" // 0x00030003 - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |S3|S2|S1|S0| "lwx $t1, %[src_stride](%[src_ptr]) \n" // |T3|T2|T1|T0| @@ -477,7 +470,6 @@ void ScaleRowDown38_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, ".set push \n" ".set noreorder \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |3|2|1|0| "lw $t1, 4(%[src_ptr]) \n" // |7|6|5|4| @@ -528,7 +520,6 @@ void ScaleRowDown38_2_Box_MIPS_DSPR2(const uint8* src_ptr, ptrdiff_t src_stride, ".set push \n" ".set noreorder \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |S3|S2|S1|S0| "lw $t1, 4(%[src_ptr]) \n" // |S7|S6|S5|S4| @@ -586,7 +577,6 @@ void ScaleRowDown38_3_Box_MIPS_DSPR2(const uint8* src_ptr, ".set push \n" ".set noreorder \n" - ".p2align 2 \n" "1: \n" "lw $t0, 0(%[src_ptr]) \n" // |S3|S2|S1|S0| "lw $t1, 4(%[src_ptr]) \n" // |S7|S6|S5|S4| diff --git a/TMessagesProj/jni/libyuv/source/scale_neon.cc b/TMessagesProj/jni/libyuv/source/scale_neon.cc index 1b8a5ba5..10856cf8 100644 --- a/TMessagesProj/jni/libyuv/source/scale_neon.cc +++ b/TMessagesProj/jni/libyuv/source/scale_neon.cc @@ -16,7 +16,8 @@ extern "C" { #endif // This module is for GCC Neon. -#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) +#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \ + !defined(__aarch64__) // NEON downscalers with interpolation. // Provided by Fritz Koenig @@ -25,7 +26,6 @@ extern "C" { void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( - ".p2align 2 \n" "1: \n" // load even pixels into q0, odd into q1 MEMACCESS(0) @@ -42,13 +42,35 @@ void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, ); } +// Read 32x1 average down and write 16x1. +void ScaleRowDown2Linear_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width) { + asm volatile ( + "1: \n" + MEMACCESS(0) + "vld1.8 {q0, q1}, [%0]! \n" // load pixels and post inc + "subs %2, %2, #16 \n" // 16 processed per loop + "vpaddl.u8 q0, q0 \n" // add adjacent + "vpaddl.u8 q1, q1 \n" + "vrshrn.u16 d0, q0, #1 \n" // downshift, round and pack + "vrshrn.u16 d1, q1, #1 \n" + MEMACCESS(1) + "vst1.8 {q0}, [%1]! \n" + "bgt 1b \n" + : "+r"(src_ptr), // %0 + "+r"(dst), // %1 + "+r"(dst_width) // %2 + : + : "q0", "q1" // Clobber List + ); +} + // Read 32x2 average down and write 16x1. void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( // change the stride to row 2 pointer "add %1, %0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0, q1}, [%0]! \n" // load row 1 and post inc @@ -76,7 +98,6 @@ void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, void ScaleRowDown4_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // src line 0 @@ -98,7 +119,6 @@ void ScaleRowDown4Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, const uint8* src_ptr2 = src_ptr + src_stride * 2; const uint8* src_ptr3 = src_ptr + src_stride * 3; asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {q0}, [%0]! \n" // load up 16x4 @@ -137,7 +157,6 @@ void ScaleRowDown34_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { asm volatile ( - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // src line 0 @@ -160,7 +179,6 @@ void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, asm volatile ( "vmov.u8 d24, #3 \n" "add %3, %0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // src line 0 @@ -220,7 +238,6 @@ void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, asm volatile ( "vmov.u8 d24, #3 \n" "add %3, %0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // src line 0 @@ -275,7 +292,6 @@ void ScaleRowDown38_NEON(const uint8* src_ptr, asm volatile ( MEMACCESS(3) "vld1.8 {q3}, [%3] \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0, d1, d2, d3}, [%0]! \n" @@ -309,7 +325,6 @@ void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, MEMACCESS(7) "vld1.8 {q15}, [%7] \n" "add %3, %0 \n" - ".p2align 2 \n" "1: \n" // d0 = 00 40 01 41 02 42 03 43 @@ -425,7 +440,6 @@ void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, MEMACCESS(5) "vld1.8 {q14}, [%5] \n" "add %3, %0 \n" - ".p2align 2 \n" "1: \n" // d0 = 00 40 01 41 02 42 03 43 @@ -516,6 +530,110 @@ void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, ); } +void ScaleAddRows_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint16* dst_ptr, int src_width, int src_height) { + const uint8* src_tmp = NULL; + asm volatile ( + "1: \n" + "mov %0, %1 \n" + "mov r12, %5 \n" + "veor q2, q2, q2 \n" + "veor q3, q3, q3 \n" + "2: \n" + // load 16 pixels into q0 + MEMACCESS(0) + "vld1.8 {q0}, [%0], %3 \n" + "vaddw.u8 q3, q3, d1 \n" + "vaddw.u8 q2, q2, d0 \n" + "subs r12, r12, #1 \n" + "bgt 2b \n" + MEMACCESS(2) + "vst1.16 {q2, q3}, [%2]! \n" // store pixels + "add %1, %1, #16 \n" + "subs %4, %4, #16 \n" // 16 processed per loop + "bgt 1b \n" + : "+r"(src_tmp), // %0 + "+r"(src_ptr), // %1 + "+r"(dst_ptr), // %2 + "+r"(src_stride), // %3 + "+r"(src_width), // %4 + "+r"(src_height) // %5 + : + : "memory", "cc", "r12", "q0", "q1", "q2", "q3" // Clobber List + ); +} + +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD2_DATA8_LANE(n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "vld2.8 {d6["#n"], d7["#n"]}, [%6] \n" + +void ScaleFilterCols_NEON(uint8* dst_ptr, const uint8* src_ptr, + int dst_width, int x, int dx) { + int dx_offset[4] = {0, 1, 2, 3}; + int* tmp = dx_offset; + const uint8* src_tmp = src_ptr; + asm volatile ( + "vdup.32 q0, %3 \n" // x + "vdup.32 q1, %4 \n" // dx + "vld1.32 {q2}, [%5] \n" // 0 1 2 3 + "vshl.i32 q3, q1, #2 \n" // 4 * dx + "vmul.s32 q1, q1, q2 \n" + // x , x + 1 * dx, x + 2 * dx, x + 3 * dx + "vadd.s32 q1, q1, q0 \n" + // x + 4 * dx, x + 5 * dx, x + 6 * dx, x + 7 * dx + "vadd.s32 q2, q1, q3 \n" + "vshl.i32 q0, q3, #1 \n" // 8 * dx + "1: \n" + LOAD2_DATA8_LANE(0) + LOAD2_DATA8_LANE(1) + LOAD2_DATA8_LANE(2) + LOAD2_DATA8_LANE(3) + LOAD2_DATA8_LANE(4) + LOAD2_DATA8_LANE(5) + LOAD2_DATA8_LANE(6) + LOAD2_DATA8_LANE(7) + "vmov q10, q1 \n" + "vmov q11, q2 \n" + "vuzp.16 q10, q11 \n" + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + "vsubl.s16 q11, d18, d16 \n" + "vsubl.s16 q12, d19, d17 \n" + "vmovl.u16 q13, d20 \n" + "vmovl.u16 q10, d21 \n" + "vmul.s32 q11, q11, q13 \n" + "vmul.s32 q12, q12, q10 \n" + "vshrn.s32 d18, q11, #16 \n" + "vshrn.s32 d19, q12, #16 \n" + "vadd.s16 q8, q8, q9 \n" + "vmovn.s16 d6, q8 \n" + + MEMACCESS(0) + "vst1.8 {d6}, [%0]! \n" // store pixels + "vadd.s32 q1, q1, q0 \n" + "vadd.s32 q2, q2, q0 \n" + "subs %2, %2, #8 \n" // 8 processed per loop + "bgt 1b \n" + : "+r"(dst_ptr), // %0 + "+r"(src_ptr), // %1 + "+r"(dst_width), // %2 + "+r"(x), // %3 + "+r"(dx), // %4 + "+r"(tmp), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "q0", "q1", "q2", "q3", + "q8", "q9", "q10", "q11", "q12", "q13" + ); +} + +#undef LOAD2_DATA8_LANE + // 16x2 -> 16x1 void ScaleFilterRows_NEON(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride, @@ -618,7 +736,6 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( - ".p2align 2 \n" "1: \n" // load even pixels into q0, odd into q1 MEMACCESS(0) @@ -639,12 +756,39 @@ void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, ); } +void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width) { + asm volatile ( + "1: \n" + MEMACCESS(0) + "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. + MEMACCESS(0) + "vld4.8 {d1, d3, d5, d7}, [%0]! \n" // load next 8 ARGB pixels. + "subs %2, %2, #8 \n" // 8 processed per loop + "vpaddl.u8 q0, q0 \n" // B 16 bytes -> 8 shorts. + "vpaddl.u8 q1, q1 \n" // G 16 bytes -> 8 shorts. + "vpaddl.u8 q2, q2 \n" // R 16 bytes -> 8 shorts. + "vpaddl.u8 q3, q3 \n" // A 16 bytes -> 8 shorts. + "vrshrn.u16 d0, q0, #1 \n" // downshift, round and pack + "vrshrn.u16 d1, q1, #1 \n" + "vrshrn.u16 d2, q2, #1 \n" + "vrshrn.u16 d3, q3, #1 \n" + MEMACCESS(1) + "vst4.8 {d0, d1, d2, d3}, [%1]! \n" + "bgt 1b \n" + : "+r"(src_argb), // %0 + "+r"(dst_argb), // %1 + "+r"(dst_width) // %2 + : + : "memory", "cc", "q0", "q1", "q2", "q3" // Clobber List + ); +} + void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( // change the stride to row 2 pointer "add %1, %1, %0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld4.8 {d0, d2, d4, d6}, [%0]! \n" // load 8 ARGB pixels. @@ -685,7 +829,6 @@ void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, uint8* dst_argb, int dst_width) { asm volatile ( "mov r12, %3, lsl #2 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.32 {d0[0]}, [%0], r12 \n" @@ -715,7 +858,6 @@ void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, asm volatile ( "mov r12, %4, lsl #2 \n" "add %1, %1, %0 \n" - ".p2align 2 \n" "1: \n" MEMACCESS(0) "vld1.8 {d0}, [%0], r12 \n" // Read 4 2x2 blocks -> 2x1 @@ -756,7 +898,118 @@ void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, ); } -#endif // __ARM_NEON__ +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD1_DATA32_LANE(dn, n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5, lsl #2 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "vld1.32 {"#dn"["#n"]}, [%6] \n" + +void ScaleARGBCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx) { + int tmp = 0; + const uint8* src_tmp = src_argb; + asm volatile ( + "1: \n" + LOAD1_DATA32_LANE(d0, 0) + LOAD1_DATA32_LANE(d0, 1) + LOAD1_DATA32_LANE(d1, 0) + LOAD1_DATA32_LANE(d1, 1) + LOAD1_DATA32_LANE(d2, 0) + LOAD1_DATA32_LANE(d2, 1) + LOAD1_DATA32_LANE(d3, 0) + LOAD1_DATA32_LANE(d3, 1) + + MEMACCESS(0) + "vst1.32 {q0, q1}, [%0]! \n" // store pixels + "subs %2, %2, #8 \n" // 8 processed per loop + "bgt 1b \n" + : "+r"(dst_argb), // %0 + "+r"(src_argb), // %1 + "+r"(dst_width), // %2 + "+r"(x), // %3 + "+r"(dx), // %4 + "+r"(tmp), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "q0", "q1" + ); +} + +#undef LOAD1_DATA32_LANE + +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD2_DATA32_LANE(dn1, dn2, n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5, lsl #2 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "vld2.32 {"#dn1"["#n"], "#dn2"["#n"]}, [%6] \n" + +void ScaleARGBFilterCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx) { + int dx_offset[4] = {0, 1, 2, 3}; + int* tmp = dx_offset; + const uint8* src_tmp = src_argb; + asm volatile ( + "vdup.32 q0, %3 \n" // x + "vdup.32 q1, %4 \n" // dx + "vld1.32 {q2}, [%5] \n" // 0 1 2 3 + "vshl.i32 q9, q1, #2 \n" // 4 * dx + "vmul.s32 q1, q1, q2 \n" + "vmov.i8 q3, #0x7f \n" // 0x7F + "vmov.i16 q15, #0x7f \n" // 0x7F + // x , x + 1 * dx, x + 2 * dx, x + 3 * dx + "vadd.s32 q8, q1, q0 \n" + "1: \n" + // d0, d1: a + // d2, d3: b + LOAD2_DATA32_LANE(d0, d2, 0) + LOAD2_DATA32_LANE(d0, d2, 1) + LOAD2_DATA32_LANE(d1, d3, 0) + LOAD2_DATA32_LANE(d1, d3, 1) + "vshrn.i32 d22, q8, #9 \n" + "vand.16 d22, d22, d30 \n" + "vdup.8 d24, d22[0] \n" + "vdup.8 d25, d22[2] \n" + "vdup.8 d26, d22[4] \n" + "vdup.8 d27, d22[6] \n" + "vext.8 d4, d24, d25, #4 \n" + "vext.8 d5, d26, d27, #4 \n" // f + "veor.8 q10, q2, q3 \n" // 0x7f ^ f + "vmull.u8 q11, d0, d20 \n" + "vmull.u8 q12, d1, d21 \n" + "vmull.u8 q13, d2, d4 \n" + "vmull.u8 q14, d3, d5 \n" + "vadd.i16 q11, q11, q13 \n" + "vadd.i16 q12, q12, q14 \n" + "vshrn.i16 d0, q11, #7 \n" + "vshrn.i16 d1, q12, #7 \n" + + MEMACCESS(0) + "vst1.32 {d0, d1}, [%0]! \n" // store pixels + "vadd.s32 q8, q8, q9 \n" + "subs %2, %2, #4 \n" // 4 processed per loop + "bgt 1b \n" + : "+r"(dst_argb), // %0 + "+r"(src_argb), // %1 + "+r"(dst_width), // %2 + "+r"(x), // %3 + "+r"(dx), // %4 + "+r"(tmp), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15" + ); +} + +#undef LOAD2_DATA32_LANE + +#endif // defined(__ARM_NEON__) && !defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/scale_neon64.cc b/TMessagesProj/jni/libyuv/source/scale_neon64.cc index 44df55c6..1d551935 100644 --- a/TMessagesProj/jni/libyuv/source/scale_neon64.cc +++ b/TMessagesProj/jni/libyuv/source/scale_neon64.cc @@ -8,16 +8,18 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include "libyuv/scale.h" #include "libyuv/row.h" +#include "libyuv/scale_row.h" #ifdef __cplusplus namespace libyuv { extern "C" { #endif -// This module is for GCC Neon. +// This module is for GCC Neon armv8 64 bit. #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) -#ifdef HAS_SCALEROWDOWN2_NEON + // Read 32x1 throw away even pixels, and write 16x1. void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { @@ -25,11 +27,11 @@ void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "1: \n" // load even pixels into v0, odd into v1 MEMACCESS(0) - "ld2 {v0.16b, v1.16b}, [%0], #32 \n" - "subs %2, %2, #16 \n" // 16 processed per loop + "ld2 {v0.16b,v1.16b}, [%0], #32 \n" + "subs %w2, %w2, #16 \n" // 16 processed per loop MEMACCESS(1) "st1 {v1.16b}, [%1], #16 \n" // store odd pixels - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst), // %1 "+r"(dst_width) // %2 @@ -37,9 +39,30 @@ void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, : "v0", "v1" // Clobber List ); } -#endif //HAS_SCALEROWDOWN2_NEON -#ifdef HAS_SCALEROWDOWN2_NEON +// Read 32x1 average down and write 16x1. +void ScaleRowDown2Linear_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst, int dst_width) { + asm volatile ( + "1: \n" + MEMACCESS(0) + "ld1 {v0.16b,v1.16b}, [%0], #32 \n" // load pixels and post inc + "subs %w2, %w2, #16 \n" // 16 processed per loop + "uaddlp v0.8h, v0.16b \n" // add adjacent + "uaddlp v1.8h, v1.16b \n" + "rshrn v0.8b, v0.8h, #1 \n" // downshift, round and pack + "rshrn2 v0.16b, v1.8h, #1 \n" + MEMACCESS(1) + "st1 {v0.16b}, [%1], #16 \n" + "b.gt 1b \n" + : "+r"(src_ptr), // %0 + "+r"(dst), // %1 + "+r"(dst_width) // %2 + : + : "v0", "v1" // Clobber List + ); +} + // Read 32x2 average down and write 16x1. void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { @@ -48,10 +71,10 @@ void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "add %1, %1, %0 \n" "1: \n" MEMACCESS(0) - "ld1 {v0.16b, v1.16b}, [%0], #32 \n" // load row 1 and post inc + "ld1 {v0.16b,v1.16b}, [%0], #32 \n" // load row 1 and post inc MEMACCESS(1) "ld1 {v2.16b, v3.16b}, [%1], #32 \n" // load row 2 and post inc - "subs %3, %3, #16 \n" // 16 processed per loop + "subs %w3, %w3, #16 \n" // 16 processed per loop "uaddlp v0.8h, v0.16b \n" // row 1 add adjacent "uaddlp v1.8h, v1.16b \n" "uadalp v0.8h, v2.16b \n" // row 2 add adjacent + row1 @@ -60,7 +83,7 @@ void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "rshrn2 v0.16b, v1.8h, #2 \n" MEMACCESS(2) "st1 {v0.16b}, [%2], #16 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(src_stride), // %1 "+r"(dst), // %2 @@ -69,19 +92,17 @@ void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, : "v0", "v1", "v2", "v3" // Clobber List ); } -#endif //HAS_SCALEROWDOWN2_NEON -#ifdef HAS_SCALEROWDOWN4_NEON void ScaleRowDown4_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { asm volatile ( "1: \n" MEMACCESS(0) - "ld4 {v0.8b-3.8b}, [%0], #32 \n" // src line 0 - "subs %2, %2, #8 \n" // 8 processed per loop + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // src line 0 + "subs %w2, %w2, #8 \n" // 8 processed per loop MEMACCESS(1) "st1 {v2.8b}, [%1], #8 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 "+r"(dst_width) // %2 @@ -89,9 +110,7 @@ void ScaleRowDown4_NEON(const uint8* src_ptr, ptrdiff_t src_stride, : "v0", "v1", "v2", "v3", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN4_NEON -#ifdef HAS_SCALEROWDOWN4_NEON void ScaleRowDown4Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { const uint8* src_ptr1 = src_ptr + src_stride; @@ -102,12 +121,12 @@ asm volatile ( MEMACCESS(0) "ld1 {v0.16b}, [%0], #16 \n" // load up 16x4 MEMACCESS(3) - "ld1 {v1.16b}, [%3], #16 \n" + "ld1 {v1.16b}, [%2], #16 \n" MEMACCESS(4) - "ld1 {v2.16b}, [%4], #16 \n" + "ld1 {v2.16b}, [%3], #16 \n" MEMACCESS(5) - "ld1 {v3.16b}, [%5], #16 \n" - "subs %2, %2, #4 \n" + "ld1 {v3.16b}, [%4], #16 \n" + "subs %w5, %w5, #4 \n" "uaddlp v0.8h, v0.16b \n" "uadalp v0.8h, v1.16b \n" "uadalp v0.8h, v2.16b \n" @@ -116,20 +135,18 @@ asm volatile ( "rshrn v0.8b, v0.8h, #4 \n" // divide by 16 w/rounding MEMACCESS(1) "st1 {v0.s}[0], [%1], #4 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(src_ptr1), // %3 - "+r"(src_ptr2), // %4 - "+r"(src_ptr3) // %5 + "+r"(src_ptr1), // %2 + "+r"(src_ptr2), // %3 + "+r"(src_ptr3), // %4 + "+r"(dst_width) // %5 : : "v0", "v1", "v2", "v3", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN4_NEON -#ifdef HAS_SCALEROWDOWN34_NEON // Down scale from 4 to 3 pixels. Use the neon multilane read/write // to load up the every 4th pixel into a 4 different registers. // Point samples 32 pixels to 24 pixels. @@ -139,12 +156,12 @@ void ScaleRowDown34_NEON(const uint8* src_ptr, asm volatile ( "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // src line 0 - "subs %2, %2, #24 \n" - "mov v2.8b, v3.8b \n" // order v0, v1, v2 + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // src line 0 + "subs %w2, %w2, #24 \n" + "orr v2.16b, v3.16b, v3.16b \n" // order v0, v1, v2 MEMACCESS(1) - "st3 {v0.8b-v2.8b}, [%1], #24 \n" - "bgt 1b \n" + "st3 {v0.8b,v1.8b,v2.8b}, [%1], #24 \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 "+r"(dst_width) // %2 @@ -152,9 +169,7 @@ void ScaleRowDown34_NEON(const uint8* src_ptr, : "v0", "v1", "v2", "v3", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN34_NEON -#ifdef HAS_SCALEROWDOWN34_NEON void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -163,10 +178,10 @@ void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, "add %3, %3, %0 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // src line 0 + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // src line 0 MEMACCESS(3) - "ld4 {v4.8b-v7.8b}, [%3], #32 \n" // src line 1 - "subs %2, %2, #24 \n" + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%3], #32 \n" // src line 1 + "subs %w2, %w2, #24 \n" // filter src line 0 with src line 1 // expand chars to shorts to allow for room @@ -202,9 +217,9 @@ void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, "uqrshrn v2.8b, v16.8h, #2 \n" MEMACCESS(1) - "st3 {v0.8b-v2.8b}, [%1], #24 \n" + "st3 {v0.8b,v1.8b,v2.8b}, [%1], #24 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 "+r"(dst_width), // %2 @@ -214,9 +229,7 @@ void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, "v20", "memory", "cc" ); } -#endif //ScaleRowDown34_0_Box_NEON -#ifdef HAS_SCALEROWDOWN34_NEON void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -225,10 +238,10 @@ void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, "add %3, %3, %0 \n" "1: \n" MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" // src line 0 + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" // src line 0 MEMACCESS(3) - "ld4 {v4.8b-v7.8b}, [%3], #32 \n" // src line 1 - "subs %2, %2, #24 \n" + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%3], #32 \n" // src line 1 + "subs %w2, %w2, #24 \n" // average src line 0 with src line 1 "urhadd v0.8b, v0.8b, v4.8b \n" "urhadd v1.8b, v1.8b, v5.8b \n" @@ -249,8 +262,8 @@ void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, "uqrshrn v2.8b, v4.8h, #2 \n" MEMACCESS(1) - "st3 {v0.8b-v2.8b}, [%1], #24 \n" - "bgt 1b \n" + "st3 {v0.8b,v1.8b,v2.8b}, [%1], #24 \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 "+r"(dst_width), // %2 @@ -259,9 +272,7 @@ void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v20", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN34_NEON -#ifdef HAS_SCALEROWDOWN38_NEON static uvec8 kShuf38 = { 0, 3, 6, 8, 11, 14, 16, 19, 22, 24, 27, 30, 0, 0, 0, 0 }; static uvec8 kShuf38_2 = @@ -282,14 +293,14 @@ void ScaleRowDown38_NEON(const uint8* src_ptr, "ld1 {v3.16b}, [%3] \n" "1: \n" MEMACCESS(0) - "ld1 {v0.16b, v1.16b}, [%0], #32 \n" - "subs %2, %2, #12 \n" - "tbl v2.16b, {v0.16b, v1.16b}, v3.16b \n" + "ld1 {v0.16b,v1.16b}, [%0], #32 \n" + "subs %w2, %w2, #12 \n" + "tbl v2.16b, {v0.16b,v1.16b}, v3.16b \n" MEMACCESS(1) "st1 {v2.8b}, [%1], #8 \n" MEMACCESS(1) "st1 {v2.s}[2], [%1], #4 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 "+r"(dst_width) // %2 @@ -298,14 +309,12 @@ void ScaleRowDown38_NEON(const uint8* src_ptr, ); } -#endif //HAS_SCALEROWDOWN38_NEON - -#ifdef HAS_SCALEROWDOWN38_NEON // 32x3 -> 12x1 void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { const uint8* src_ptr1 = src_ptr + src_stride * 2; + ptrdiff_t tmp_src_stride = src_stride; asm volatile ( MEMACCESS(5) @@ -314,7 +323,7 @@ void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, "ld1 {v30.16b}, [%6] \n" MEMACCESS(7) "ld1 {v31.8h}, [%7] \n" - "add %3, %3, %0 \n" + "add %2, %2, %0 \n" "1: \n" // 00 40 01 41 02 42 03 43 @@ -322,12 +331,12 @@ void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, // 20 60 21 61 22 62 23 63 // 30 70 31 71 32 72 33 73 MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" MEMACCESS(3) - "ld4 {v4.8b-v7.8b}, [%3], #32 \n" + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%2], #32 \n" MEMACCESS(4) - "ld4 {v16.8b-v19.8b}, [%4], #32 \n" - "subs %2, %2, #12 \n" + "ld4 {v16.8b,v17.8b,v18.8b,v19.8b}, [%3], #32 \n" + "subs %w4, %w4, #12 \n" // Shuffle the input data around to get align the data // so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 @@ -414,12 +423,12 @@ void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, "st1 {v3.8b}, [%1], #8 \n" MEMACCESS(1) "st1 {v3.s}[2], [%1], #4 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_ptr), // %0 "+r"(dst_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(src_stride), // %3 - "+r"(src_ptr1) // %4 + "+r"(tmp_src_stride), // %2 + "+r"(src_ptr1), // %3 + "+r"(dst_width) // %4 : "r"(&kMult38_Div6), // %5 "r"(&kShuf38_2), // %6 "r"(&kMult38_Div9) // %7 @@ -428,19 +437,19 @@ void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, "v30", "v31", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN38_NEON -#ifdef HAS_SCALEROWDOWN38_NEON // 32x2 -> 12x1 void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { + // TODO(fbarchard): use src_stride directly for clang 3.5+. + ptrdiff_t tmp_src_stride = src_stride; asm volatile ( MEMACCESS(4) "ld1 {v30.8h}, [%4] \n" MEMACCESS(5) "ld1 {v31.16b}, [%5] \n" - "add %3, %3, %0 \n" + "add %2, %2, %0 \n" "1: \n" // 00 40 01 41 02 42 03 43 @@ -448,10 +457,10 @@ void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, // 20 60 21 61 22 62 23 63 // 30 70 31 71 32 72 33 73 MEMACCESS(0) - "ld4 {v0.8b-v3.8b}, [%0], #32 \n" + "ld4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%0], #32 \n" MEMACCESS(3) - "ld4 {v4.8b-v7.8b}, [%3], #32 \n" - "subs %2, %2, #12 \n" + "ld4 {v4.8b,v5.8b,v6.8b,v7.8b}, [%2], #32 \n" + "subs %w3, %w3, #12 \n" // Shuffle the input data around to get align the data // so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 @@ -524,18 +533,124 @@ void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, "st1 {v3.8b}, [%1], #8 \n" MEMACCESS(1) "st1 {v3.s}[2], [%1], #4 \n" - "bgt 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(src_stride) // %3 - : "r"(&kMult38_Div6), // %4 - "r"(&kShuf38_2) // %5 + "b.gt 1b \n" + : "+r"(src_ptr), // %0 + "+r"(dst_ptr), // %1 + "+r"(tmp_src_stride), // %2 + "+r"(dst_width) // %3 + : "r"(&kMult38_Div6), // %4 + "r"(&kShuf38_2) // %5 : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16", "v17", "v18", "v19", "v30", "v31", "memory", "cc" ); } -#endif //HAS_SCALEROWDOWN38_NEON + +void ScaleAddRows_NEON(const uint8* src_ptr, ptrdiff_t src_stride, + uint16* dst_ptr, int src_width, int src_height) { + const uint8* src_tmp = NULL; + asm volatile ( + "1: \n" + "mov %0, %1 \n" + "mov w12, %w5 \n" + "eor v2.16b, v2.16b, v2.16b \n" + "eor v3.16b, v3.16b, v3.16b \n" + "2: \n" + // load 16 pixels into q0 + MEMACCESS(0) + "ld1 {v0.16b}, [%0], %3 \n" + "uaddw2 v3.8h, v3.8h, v0.16b \n" + "uaddw v2.8h, v2.8h, v0.8b \n" + "subs w12, w12, #1 \n" + "b.gt 2b \n" + MEMACCESS(2) + "st1 {v2.8h, v3.8h}, [%2], #32 \n" // store pixels + "add %1, %1, #16 \n" + "subs %w4, %w4, #16 \n" // 16 processed per loop + "b.gt 1b \n" + : "+r"(src_tmp), // %0 + "+r"(src_ptr), // %1 + "+r"(dst_ptr), // %2 + "+r"(src_stride), // %3 + "+r"(src_width), // %4 + "+r"(src_height) // %5 + : + : "memory", "cc", "w12", "v0", "v1", "v2", "v3" // Clobber List + ); +} + +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD2_DATA8_LANE(n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "ld2 {v4.b, v5.b}["#n"], [%6] \n" + +void ScaleFilterCols_NEON(uint8* dst_ptr, const uint8* src_ptr, + int dst_width, int x, int dx) { + int dx_offset[4] = {0, 1, 2, 3}; + int* tmp = dx_offset; + const uint8* src_tmp = src_ptr; + int64 dst_width64 = (int64) dst_width; // Work around ios 64 bit warning. + int64 x64 = (int64) x; + int64 dx64 = (int64) dx; + asm volatile ( + "dup v0.4s, %w3 \n" // x + "dup v1.4s, %w4 \n" // dx + "ld1 {v2.4s}, [%5] \n" // 0 1 2 3 + "shl v3.4s, v1.4s, #2 \n" // 4 * dx + "mul v1.4s, v1.4s, v2.4s \n" + // x , x + 1 * dx, x + 2 * dx, x + 3 * dx + "add v1.4s, v1.4s, v0.4s \n" + // x + 4 * dx, x + 5 * dx, x + 6 * dx, x + 7 * dx + "add v2.4s, v1.4s, v3.4s \n" + "shl v0.4s, v3.4s, #1 \n" // 8 * dx + "1: \n" + LOAD2_DATA8_LANE(0) + LOAD2_DATA8_LANE(1) + LOAD2_DATA8_LANE(2) + LOAD2_DATA8_LANE(3) + LOAD2_DATA8_LANE(4) + LOAD2_DATA8_LANE(5) + LOAD2_DATA8_LANE(6) + LOAD2_DATA8_LANE(7) + "mov v6.16b, v1.16b \n" + "mov v7.16b, v2.16b \n" + "uzp1 v6.8h, v6.8h, v7.8h \n" + "ushll v4.8h, v4.8b, #0 \n" + "ushll v5.8h, v5.8b, #0 \n" + "ssubl v16.4s, v5.4h, v4.4h \n" + "ssubl2 v17.4s, v5.8h, v4.8h \n" + "ushll v7.4s, v6.4h, #0 \n" + "ushll2 v6.4s, v6.8h, #0 \n" + "mul v16.4s, v16.4s, v7.4s \n" + "mul v17.4s, v17.4s, v6.4s \n" + "shrn v6.4h, v16.4s, #16 \n" + "shrn2 v6.8h, v17.4s, #16 \n" + "add v4.8h, v4.8h, v6.8h \n" + "xtn v4.8b, v4.8h \n" + + MEMACCESS(0) + "st1 {v4.8b}, [%0], #8 \n" // store pixels + "add v1.4s, v1.4s, v0.4s \n" + "add v2.4s, v2.4s, v0.4s \n" + "subs %w2, %w2, #8 \n" // 8 processed per loop + "b.gt 1b \n" + : "+r"(dst_ptr), // %0 + "+r"(src_ptr), // %1 + "+r"(dst_width64), // %2 + "+r"(x64), // %3 + "+r"(dx64), // %4 + "+r"(tmp), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "v0", "v1", "v2", "v3", + "v4", "v5", "v6", "v7", "v16", "v17" + ); +} + +#undef LOAD2_DATA8_LANE // 16x2 -> 16x1 void ScaleFilterRows_NEON(uint8* dst_ptr, @@ -543,15 +658,15 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, int dst_width, int source_y_fraction) { int y_fraction = 256 - source_y_fraction; asm volatile ( - "cmp %4, #0 \n" - "beq 100f \n" + "cmp %w4, #0 \n" + "b.eq 100f \n" "add %2, %2, %1 \n" - "cmp %4, #64 \n" - "beq 75f \n" - "cmp %4, #128 \n" - "beq 50f \n" - "cmp %4, #192 \n" - "beq 25f \n" + "cmp %w4, #64 \n" + "b.eq 75f \n" + "cmp %w4, #128 \n" + "b.eq 50f \n" + "cmp %w4, #192 \n" + "b.eq 25f \n" "dup v5.8b, %w4 \n" "dup v4.8b, %w5 \n" @@ -561,7 +676,7 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, "ld1 {v0.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "umull v6.8h, v0.8b, v4.8b \n" "umull2 v7.8h, v0.16b, v4.16b \n" "umlal v6.8h, v1.8b, v5.8b \n" @@ -570,7 +685,7 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, "rshrn2 v0.16b, v7.8h, #8 \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 1b \n" + "b.gt 1b \n" "b 99f \n" // Blend 25 / 75. @@ -579,12 +694,12 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, "ld1 {v0.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "urhadd v0.16b, v0.16b, v1.16b \n" "urhadd v0.16b, v0.16b, v1.16b \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 25b \n" + "b.gt 25b \n" "b 99f \n" // Blend 50 / 50. @@ -593,11 +708,11 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, "ld1 {v0.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v1.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "urhadd v0.16b, v0.16b, v1.16b \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 50b \n" + "b.gt 50b \n" "b 99f \n" // Blend 75 / 25. @@ -606,22 +721,22 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, "ld1 {v1.16b}, [%1], #16 \n" MEMACCESS(2) "ld1 {v0.16b}, [%2], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" "urhadd v0.16b, v0.16b, v1.16b \n" "urhadd v0.16b, v0.16b, v1.16b \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 75b \n" + "b.gt 75b \n" "b 99f \n" // Blend 100 / 0 - Copy row unchanged. "100: \n" MEMACCESS(1) "ld1 {v0.16b}, [%1], #16 \n" - "subs %3, %3, #16 \n" + "subs %w3, %w3, #16 \n" MEMACCESS(0) "st1 {v0.16b}, [%0], #16 \n" - "bgt 100b \n" + "b.gt 100b \n" "99: \n" MEMACCESS(0) @@ -637,7 +752,6 @@ void ScaleFilterRows_NEON(uint8* dst_ptr, ); } -#ifdef HAS_SCALEARGBROWDOWN2_NEON void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( @@ -647,12 +761,12 @@ void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "ld2 {v0.4s, v1.4s}, [%0], #32 \n" MEMACCESS (0) "ld2 {v2.4s, v3.4s}, [%0], #32 \n" - "subs %2, %2, #8 \n" // 8 processed per loop + "subs %w2, %w2, #8 \n" // 8 processed per loop MEMACCESS (1) "st1 {v1.16b}, [%1], #16 \n" // store odd pixels MEMACCESS (1) "st1 {v3.16b}, [%1], #16 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r" (src_ptr), // %0 "+r" (dst), // %1 "+r" (dst_width) // %2 @@ -660,9 +774,34 @@ void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, : "memory", "cc", "v0", "v1", "v2", "v3" // Clobber List ); } -#endif //HAS_SCALEARGBROWDOWN2_NEON -#ifdef HAS_SCALEARGBROWDOWN2_NEON +void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, ptrdiff_t src_stride, + uint8* dst_argb, int dst_width) { + asm volatile ( + "1: \n" + MEMACCESS (0) + // load 8 ARGB pixels. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" + "subs %w2, %w2, #8 \n" // 8 processed per loop. + "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. + "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. + "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. + "uaddlp v3.8h, v3.16b \n" // A 16 bytes -> 8 shorts. + "rshrn v0.8b, v0.8h, #1 \n" // downshift, round and pack + "rshrn v1.8b, v1.8h, #1 \n" + "rshrn v2.8b, v2.8h, #1 \n" + "rshrn v3.8b, v3.8h, #1 \n" + MEMACCESS (1) + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%1], #32 \n" + "b.gt 1b \n" + : "+r"(src_argb), // %0 + "+r"(dst_argb), // %1 + "+r"(dst_width) // %2 + : + : "memory", "cc", "v0", "v1", "v2", "v3" // Clobber List + ); +} + void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst, int dst_width) { asm volatile ( @@ -670,14 +809,14 @@ void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "add %1, %1, %0 \n" "1: \n" MEMACCESS (0) - "ld4 {v0.16b - v3.16b}, [%0], #64 \n" // load 8 ARGB pixels. - "subs %3, %3, #8 \n" // 8 processed per loop. + "ld4 {v0.16b,v1.16b,v2.16b,v3.16b}, [%0], #64 \n" // load 8 ARGB pixels. + "subs %w3, %w3, #8 \n" // 8 processed per loop. "uaddlp v0.8h, v0.16b \n" // B 16 bytes -> 8 shorts. "uaddlp v1.8h, v1.16b \n" // G 16 bytes -> 8 shorts. "uaddlp v2.8h, v2.16b \n" // R 16 bytes -> 8 shorts. "uaddlp v3.8h, v3.16b \n" // A 16 bytes -> 8 shorts. MEMACCESS (1) - "ld4 {v16.16b - v19.16b}, [%1], #64 \n" // load 8 more ARGB pixels. + "ld4 {v16.16b,v17.16b,v18.16b,v19.16b}, [%1], #64 \n" // load 8 more ARGB pixels. "uadalp v0.8h, v16.16b \n" // B 16 bytes -> 8 shorts. "uadalp v1.8h, v17.16b \n" // G 16 bytes -> 8 shorts. "uadalp v2.8h, v18.16b \n" // R 16 bytes -> 8 shorts. @@ -687,8 +826,8 @@ void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, "rshrn v2.8b, v2.8h, #2 \n" "rshrn v3.8b, v3.8h, #2 \n" MEMACCESS (2) - "st4 {v0.8b - v3.8b}, [%2], #32 \n" - "bgt 1b \n" + "st4 {v0.8b,v1.8b,v2.8b,v3.8b}, [%2], #32 \n" + "b.gt 1b \n" : "+r" (src_ptr), // %0 "+r" (src_stride), // %1 "+r" (dst), // %2 @@ -697,9 +836,7 @@ void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, : "memory", "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19" ); } -#endif //HAS_SCALEARGBROWDOWN2_NEON -#ifdef HAS_SCALEARGBROWDOWNEVEN_NEON // Reads 4 pixels at a time. // Alignment requirement: src_argb 4 byte aligned. void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride, @@ -714,23 +851,21 @@ void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride, "ld1 {v0.s}[2], [%0], %3 \n" MEMACCESS(0) "ld1 {v0.s}[3], [%0], %3 \n" - "subs %2, %2, #4 \n" // 4 pixels per loop. + "subs %w2, %w2, #4 \n" // 4 pixels per loop. MEMACCESS(1) "st1 {v0.16b}, [%1], #16 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(dst_argb), // %1 "+r"(dst_width) // %2 - : "r"(src_stepx * 4) // %3 + : "r"((int64)(src_stepx * 4)) // %3 : "memory", "cc", "v0" ); } -#endif //HAS_SCALEARGBROWDOWNEVEN_NEON -#ifdef HAS_SCALEARGBROWDOWNEVEN_NEON // Reads 4 pixels at a time. // Alignment requirement: src_argb 4 byte aligned. -// TODO, might be worth another optimization pass in future. +// TODO(Yang Zhang): Might be worth another optimization pass in future. // It could be upgraded to 8 pixels at a time to start with. void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, @@ -739,49 +874,167 @@ void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, "add %1, %1, %0 \n" "1: \n" MEMACCESS(0) - "ld1 {v0.8b}, [%0], %4 \n" // Read 4 2x2 blocks -> 2x1 + "ld1 {v0.8b}, [%0], %4 \n" // Read 4 2x2 blocks -> 2x1 MEMACCESS(1) - "ld1 {v1.8b}, [%1], %4 \n" + "ld1 {v1.8b}, [%1], %4 \n" MEMACCESS(0) - "ld1 {v2.8b}, [%0], %4 \n" + "ld1 {v2.8b}, [%0], %4 \n" MEMACCESS(1) - "ld1 {v3.8b}, [%1], %4 \n" + "ld1 {v3.8b}, [%1], %4 \n" MEMACCESS(0) - "ld1 {v4.8b}, [%0], %4 \n" + "ld1 {v4.8b}, [%0], %4 \n" MEMACCESS(1) - "ld1 {v5.8b}, [%1], %4 \n" + "ld1 {v5.8b}, [%1], %4 \n" MEMACCESS(0) - "ld1 {v6.8b}, [%0], %4 \n" + "ld1 {v6.8b}, [%0], %4 \n" MEMACCESS(1) - "ld1 {v7.8b}, [%1], %4 \n" - "uaddl v0.8h, v0.8b, v1.8b \n" - "uaddl v2.8h, v2.8b, v3.8b \n" - "uaddl v4.8h, v4.8b, v5.8b \n" - "uaddl v6.8h, v6.8b, v7.8b \n" - "mov v16.d[1], v0.d[1] \n" // ab_cd -> ac_bd - "mov v0.d[1], v2.d[0] \n" - "mov v2.d[0], v16.d[1] \n" - "mov v16.d[1], v4.d[1] \n" // ef_gh -> eg_fh - "mov v4.d[1], v6.d[0] \n" - "mov v6.d[0], v16.d[1] \n" - "add v0.8h, v0.8h, v2.8h \n" // (a+b)_(c+d) - "add v4.8h, v4.8h, v6.8h \n" // (e+f)_(g+h) - "rshrn v0.8b, v0.8h, #2 \n" // first 2 pixels. - "rshrn2 v0.16b, v4.8h, #2 \n" // next 2 pixels. - "subs %3, %3, #4 \n" // 4 pixels per loop. + "ld1 {v7.8b}, [%1], %4 \n" + "uaddl v0.8h, v0.8b, v1.8b \n" + "uaddl v2.8h, v2.8b, v3.8b \n" + "uaddl v4.8h, v4.8b, v5.8b \n" + "uaddl v6.8h, v6.8b, v7.8b \n" + "mov v16.d[1], v0.d[1] \n" // ab_cd -> ac_bd + "mov v0.d[1], v2.d[0] \n" + "mov v2.d[0], v16.d[1] \n" + "mov v16.d[1], v4.d[1] \n" // ef_gh -> eg_fh + "mov v4.d[1], v6.d[0] \n" + "mov v6.d[0], v16.d[1] \n" + "add v0.8h, v0.8h, v2.8h \n" // (a+b)_(c+d) + "add v4.8h, v4.8h, v6.8h \n" // (e+f)_(g+h) + "rshrn v0.8b, v0.8h, #2 \n" // first 2 pixels. + "rshrn2 v0.16b, v4.8h, #2 \n" // next 2 pixels. + "subs %w3, %w3, #4 \n" // 4 pixels per loop. MEMACCESS(2) "st1 {v0.16b}, [%2], #16 \n" - "bgt 1b \n" + "b.gt 1b \n" : "+r"(src_argb), // %0 "+r"(src_stride), // %1 "+r"(dst_argb), // %2 "+r"(dst_width) // %3 - : "r"(src_stepx * 4) // %4 + : "r"((int64)(src_stepx * 4)) // %4 : "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16" ); } -#endif // HAS_SCALEARGBROWDOWNEVEN_NEON -#endif // __aarch64__ + +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD1_DATA32_LANE(vn, n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5, lsl #2 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "ld1 {"#vn".s}["#n"], [%6] \n" + +void ScaleARGBCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx) { + const uint8* src_tmp = src_argb; + int64 dst_width64 = (int64) dst_width; // Work around ios 64 bit warning. + int64 x64 = (int64) x; + int64 dx64 = (int64) dx; + int64 tmp64 = 0; + asm volatile ( + "1: \n" + LOAD1_DATA32_LANE(v0, 0) + LOAD1_DATA32_LANE(v0, 1) + LOAD1_DATA32_LANE(v0, 2) + LOAD1_DATA32_LANE(v0, 3) + LOAD1_DATA32_LANE(v1, 0) + LOAD1_DATA32_LANE(v1, 1) + LOAD1_DATA32_LANE(v1, 2) + LOAD1_DATA32_LANE(v1, 3) + + MEMACCESS(0) + "st1 {v0.4s, v1.4s}, [%0], #32 \n" // store pixels + "subs %w2, %w2, #8 \n" // 8 processed per loop + "b.gt 1b \n" + : "+r"(dst_argb), // %0 + "+r"(src_argb), // %1 + "+r"(dst_width64), // %2 + "+r"(x64), // %3 + "+r"(dx64), // %4 + "+r"(tmp64), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "v0", "v1" + ); +} + +#undef LOAD1_DATA32_LANE + +// TODO(Yang Zhang): Investigate less load instructions for +// the x/dx stepping +#define LOAD2_DATA32_LANE(vn1, vn2, n) \ + "lsr %5, %3, #16 \n" \ + "add %6, %1, %5, lsl #2 \n" \ + "add %3, %3, %4 \n" \ + MEMACCESS(6) \ + "ld2 {"#vn1".s, "#vn2".s}["#n"], [%6] \n" + +void ScaleARGBFilterCols_NEON(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx) { + int dx_offset[4] = {0, 1, 2, 3}; + int* tmp = dx_offset; + const uint8* src_tmp = src_argb; + int64 dst_width64 = (int64) dst_width; // Work around ios 64 bit warning. + int64 x64 = (int64) x; + int64 dx64 = (int64) dx; + asm volatile ( + "dup v0.4s, %w3 \n" // x + "dup v1.4s, %w4 \n" // dx + "ld1 {v2.4s}, [%5] \n" // 0 1 2 3 + "shl v6.4s, v1.4s, #2 \n" // 4 * dx + "mul v1.4s, v1.4s, v2.4s \n" + "movi v3.16b, #0x7f \n" // 0x7F + "movi v4.8h, #0x7f \n" // 0x7F + // x , x + 1 * dx, x + 2 * dx, x + 3 * dx + "add v5.4s, v1.4s, v0.4s \n" + "1: \n" + // d0, d1: a + // d2, d3: b + LOAD2_DATA32_LANE(v0, v1, 0) + LOAD2_DATA32_LANE(v0, v1, 1) + LOAD2_DATA32_LANE(v0, v1, 2) + LOAD2_DATA32_LANE(v0, v1, 3) + "shrn v2.4h, v5.4s, #9 \n" + "and v2.8b, v2.8b, v4.8b \n" + "dup v16.8b, v2.b[0] \n" + "dup v17.8b, v2.b[2] \n" + "dup v18.8b, v2.b[4] \n" + "dup v19.8b, v2.b[6] \n" + "ext v2.8b, v16.8b, v17.8b, #4 \n" + "ext v17.8b, v18.8b, v19.8b, #4 \n" + "ins v2.d[1], v17.d[0] \n" // f + "eor v7.16b, v2.16b, v3.16b \n" // 0x7f ^ f + "umull v16.8h, v0.8b, v7.8b \n" + "umull2 v17.8h, v0.16b, v7.16b \n" + "umull v18.8h, v1.8b, v2.8b \n" + "umull2 v19.8h, v1.16b, v2.16b \n" + "add v16.8h, v16.8h, v18.8h \n" + "add v17.8h, v17.8h, v19.8h \n" + "shrn v0.8b, v16.8h, #7 \n" + "shrn2 v0.16b, v17.8h, #7 \n" + + MEMACCESS(0) + "st1 {v0.4s}, [%0], #16 \n" // store pixels + "add v5.4s, v5.4s, v6.4s \n" + "subs %w2, %w2, #4 \n" // 4 processed per loop + "b.gt 1b \n" + : "+r"(dst_argb), // %0 + "+r"(src_argb), // %1 + "+r"(dst_width64), // %2 + "+r"(x64), // %3 + "+r"(dx64), // %4 + "+r"(tmp), // %5 + "+r"(src_tmp) // %6 + : + : "memory", "cc", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v16", "v17", "v18", "v19" + ); +} + +#undef LOAD2_DATA32_LANE + +#endif // !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/scale_posix.cc b/TMessagesProj/jni/libyuv/source/scale_posix.cc deleted file mode 100644 index 352e6678..00000000 --- a/TMessagesProj/jni/libyuv/source/scale_posix.cc +++ /dev/null @@ -1,1315 +0,0 @@ -/* - * Copyright 2013 The LibYuv Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "libyuv/row.h" - -#ifdef __cplusplus -namespace libyuv { -extern "C" { -#endif - -// This module is for GCC x86 and x64. -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -// Offsets for source bytes 0 to 9 -static uvec8 kShuf0 = - { 0, 1, 3, 4, 5, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128 }; - -// Offsets for source bytes 11 to 20 with 8 subtracted = 3 to 12. -static uvec8 kShuf1 = - { 3, 4, 5, 7, 8, 9, 11, 12, 128, 128, 128, 128, 128, 128, 128, 128 }; - -// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31. -static uvec8 kShuf2 = - { 5, 7, 8, 9, 11, 12, 13, 15, 128, 128, 128, 128, 128, 128, 128, 128 }; - -// Offsets for source bytes 0 to 10 -static uvec8 kShuf01 = - { 0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10 }; - -// Offsets for source bytes 10 to 21 with 8 subtracted = 3 to 13. -static uvec8 kShuf11 = - { 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 12, 13 }; - -// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31. -static uvec8 kShuf21 = - { 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 12, 13, 13, 14, 14, 15 }; - -// Coefficients for source bytes 0 to 10 -static uvec8 kMadd01 = - { 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2 }; - -// Coefficients for source bytes 10 to 21 -static uvec8 kMadd11 = - { 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1 }; - -// Coefficients for source bytes 21 to 31 -static uvec8 kMadd21 = - { 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3 }; - -// Coefficients for source bytes 21 to 31 -static vec16 kRound34 = - { 2, 2, 2, 2, 2, 2, 2, 2 }; - -static uvec8 kShuf38a = - { 0, 3, 6, 8, 11, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }; - -static uvec8 kShuf38b = - { 128, 128, 128, 128, 128, 128, 0, 3, 6, 8, 11, 14, 128, 128, 128, 128 }; - -// Arrange words 0,3,6 into 0,1,2 -static uvec8 kShufAc = - { 0, 1, 6, 7, 12, 13, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }; - -// Arrange words 0,3,6 into 3,4,5 -static uvec8 kShufAc3 = - { 128, 128, 128, 128, 128, 128, 0, 1, 6, 7, 12, 13, 128, 128, 128, 128 }; - -// Scaling values for boxes of 3x3 and 2x3 -static uvec16 kScaleAc33 = - { 65536 / 9, 65536 / 9, 65536 / 6, 65536 / 9, 65536 / 9, 65536 / 6, 0, 0 }; - -// Arrange first value for pixels 0,1,2,3,4,5 -static uvec8 kShufAb0 = - { 0, 128, 3, 128, 6, 128, 8, 128, 11, 128, 14, 128, 128, 128, 128, 128 }; - -// Arrange second value for pixels 0,1,2,3,4,5 -static uvec8 kShufAb1 = - { 1, 128, 4, 128, 7, 128, 9, 128, 12, 128, 15, 128, 128, 128, 128, 128 }; - -// Arrange third value for pixels 0,1,2,3,4,5 -static uvec8 kShufAb2 = - { 2, 128, 5, 128, 128, 128, 10, 128, 13, 128, 128, 128, 128, 128, 128, 128 }; - -// Scaling values for boxes of 3x2 and 2x2 -static uvec16 kScaleAb2 = - { 65536 / 3, 65536 / 3, 65536 / 2, 65536 / 3, 65536 / 3, 65536 / 2, 0, 0 }; - -// GCC versions of row functions are verbatim conversions from Visual C. -// Generated using gcc disassembly on Visual C object file: -// objdump -D yuvscaler.obj >yuvscaler.txt - -void ScaleRowDown2_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void ScaleRowDown2Linear_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10, 0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psrlw $0x8,%%xmm1 \n" - "pand %%xmm5,%%xmm2 \n" - "pand %%xmm5,%%xmm3 \n" - "pavgw %%xmm2,%%xmm0 \n" - "pavgw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void ScaleRowDown2Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - MEMOPREG(movdqa,0x00,0,3,1,xmm2) // movdqa (%0,%3,1),%%xmm2 - BUNDLEALIGN - MEMOPREG(movdqa,0x10,0,3,1,xmm3) // movdqa 0x10(%0,%3,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psrlw $0x8,%%xmm1 \n" - "pand %%xmm5,%%xmm2 \n" - "pand %%xmm5,%%xmm3 \n" - "pavgw %%xmm2,%%xmm0 \n" - "pavgw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void ScaleRowDown2_Unaligned_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void ScaleRowDown2Linear_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psrlw $0x8,%%xmm1 \n" - "pand %%xmm5,%%xmm2 \n" - "pand %%xmm5,%%xmm3 \n" - "pavgw %%xmm2,%%xmm0 \n" - "pavgw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void ScaleRowDown2Box_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrlw $0x8,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu " MEMACCESS(0) ",%%xmm0 \n" - "movdqu " MEMACCESS2(0x10,0) ",%%xmm1 \n" - MEMOPREG(movdqu,0x00,0,3,1,xmm2) // movdqu (%0,%3,1),%%xmm2 - BUNDLEALIGN - MEMOPREG(movdqu,0x10,0,3,1,xmm3) // movdqu 0x10(%0,%3,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psrlw $0x8,%%xmm1 \n" - "pand %%xmm5,%%xmm2 \n" - "pand %%xmm5,%%xmm3 \n" - "pavgw %%xmm2,%%xmm0 \n" - "pavgw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm5" -#endif - ); -} - -void ScaleRowDown4_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrld $0x18,%%xmm5 \n" - "pslld $0x10,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "psrlw $0x8,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm5" -#endif - ); -} - -void ScaleRowDown4Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - intptr_t stridex3 = 0; - asm volatile ( - "pcmpeqb %%xmm7,%%xmm7 \n" - "psrlw $0x8,%%xmm7 \n" - "lea " MEMLEA4(0x00,4,4,2) ",%3 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - MEMOPREG(movdqa,0x00,0,4,1,xmm2) // movdqa (%0,%4,1),%%xmm2 - BUNDLEALIGN - MEMOPREG(movdqa,0x10,0,4,1,xmm3) // movdqa 0x10(%0,%4,1),%%xmm3 - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - MEMOPREG(movdqa,0x00,0,4,2,xmm2) // movdqa (%0,%4,2),%%xmm2 - BUNDLEALIGN - MEMOPREG(movdqa,0x10,0,4,2,xmm3) // movdqa 0x10(%0,%4,2),%%xmm3 - MEMOPREG(movdqa,0x00,0,3,1,xmm4) // movdqa (%0,%3,1),%%xmm4 - MEMOPREG(movdqa,0x10,0,3,1,xmm5) // movdqa 0x10(%0,%3,1),%%xmm5 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm4,%%xmm2 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm5,%%xmm3 \n" - "pavgb %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "movdqa %%xmm1,%%xmm3 \n" - "psrlw $0x8,%%xmm1 \n" - "pand %%xmm7,%%xmm2 \n" - "pand %%xmm7,%%xmm3 \n" - "pavgw %%xmm2,%%xmm0 \n" - "pavgw %%xmm3,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "psrlw $0x8,%%xmm0 \n" - "pand %%xmm7,%%xmm2 \n" - "pavgw %%xmm2,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x8,1) ",%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width), // %2 - "+r"(stridex3) // %3 - : "r"((intptr_t)(src_stride)) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm7" -#endif - ); -} - -void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %0,%%xmm3 \n" - "movdqa %1,%%xmm4 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kShuf0), // %0 - "m"(kShuf1), // %1 - "m"(kShuf2) // %2 - ); - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm2 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "palignr $0x8,%%xmm0,%%xmm1 \n" - "pshufb %%xmm3,%%xmm0 \n" - "pshufb %%xmm4,%%xmm1 \n" - "pshufb %%xmm5,%%xmm2 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "movq %%xmm1," MEMACCESS2(0x8,1) " \n" - "movq %%xmm2," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x18,1) ",%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" -#endif - ); -} - -void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %0,%%xmm2 \n" // kShuf01 - "movdqa %1,%%xmm3 \n" // kShuf11 - "movdqa %2,%%xmm4 \n" // kShuf21 - : - : "m"(kShuf01), // %0 - "m"(kShuf11), // %1 - "m"(kShuf21) // %2 - ); - asm volatile ( - "movdqa %0,%%xmm5 \n" // kMadd01 - "movdqa %1,%%xmm0 \n" // kMadd11 - "movdqa %2,%%xmm1 \n" // kRound34 - : - : "m"(kMadd01), // %0 - "m"(kMadd11), // %1 - "m"(kRound34) // %2 - ); - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm6 \n" - MEMOPREG(movdqa,0x00,0,3,1,xmm7) // movdqa (%0,%3),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm5,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS(1) " \n" - "movdqu " MEMACCESS2(0x8,0) ",%%xmm6 \n" - MEMOPREG(movdqu,0x8,0,3,1,xmm7) // movdqu 0x8(%0,%3),%%xmm7 - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "pmaddubsw %%xmm0,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS2(0x8,1) " \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm6 \n" - BUNDLEALIGN - MEMOPREG(movdqa,0x10,0,3,1,xmm7) // movdqa 0x10(%0,%3),%%xmm7 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm4,%%xmm6 \n" - "pmaddubsw %4,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x18,1) ",%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)), // %3 - "m"(kMadd21) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %0,%%xmm2 \n" // kShuf01 - "movdqa %1,%%xmm3 \n" // kShuf11 - "movdqa %2,%%xmm4 \n" // kShuf21 - : - : "m"(kShuf01), // %0 - "m"(kShuf11), // %1 - "m"(kShuf21) // %2 - ); - asm volatile ( - "movdqa %0,%%xmm5 \n" // kMadd01 - "movdqa %1,%%xmm0 \n" // kMadd11 - "movdqa %2,%%xmm1 \n" // kRound34 - : - : "m"(kMadd01), // %0 - "m"(kMadd11), // %1 - "m"(kRound34) // %2 - ); - - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm6 \n" - MEMOPREG(movdqa,0x00,0,3,1,xmm7) // movdqa (%0,%3,1),%%xmm7 - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm5,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS(1) " \n" - "movdqu " MEMACCESS2(0x8,0) ",%%xmm6 \n" - MEMOPREG(movdqu,0x8,0,3,1,xmm7) // movdqu 0x8(%0,%3,1),%%xmm7 - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "pmaddubsw %%xmm0,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS2(0x8,1) " \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm6 \n" - MEMOPREG(movdqa,0x10,0,3,1,xmm7) // movdqa 0x10(%0,%3,1),%%xmm7 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm4,%%xmm6 \n" - "pmaddubsw %4,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x18,1) ",%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)), // %3 - "m"(kMadd21) // %4 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ScaleRowDown38_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "pshufb %%xmm4,%%xmm0 \n" - "pshufb %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "movq %%xmm0," MEMACCESS(1) " \n" - "movhlps %%xmm0,%%xmm1 \n" - "movd %%xmm1," MEMACCESS2(0x8,1) " \n" - "lea " MEMLEA(0xc,1) ",%1 \n" - "sub $0xc,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kShuf38a), // %3 - "m"(kShuf38b) // %4 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm4", "xmm5" -#endif - ); -} - -void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %0,%%xmm2 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm4 \n" - "movdqa %3,%%xmm5 \n" - : - : "m"(kShufAb0), // %0 - "m"(kShufAb1), // %1 - "m"(kShufAb2), // %2 - "m"(kScaleAb2) // %3 - ); - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(pavgb,0x00,0,3,1,xmm0) // pavgb (%0,%3,1),%%xmm0 - "lea " MEMLEA(0x10,0) ",%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pshufb %%xmm2,%%xmm1 \n" - "movdqa %%xmm0,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "paddusw %%xmm6,%%xmm1 \n" - "pshufb %%xmm4,%%xmm0 \n" - "paddusw %%xmm0,%%xmm1 \n" - "pmulhuw %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "sub $0x6,%2 \n" - "movd %%xmm1," MEMACCESS(1) " \n" - "psrlq $0x10,%%xmm1 \n" - "movd %%xmm1," MEMACCESS2(0x2,1) " \n" - "lea " MEMLEA(0x6,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - asm volatile ( - "movdqa %0,%%xmm2 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - : - : "m"(kShufAc), // %0 - "m"(kShufAc3), // %1 - "m"(kScaleAc33) // %2 - ); - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movdqa,0x00,0,3,1,xmm6) // movdqa (%0,%3,1),%%xmm6 - "movhlps %%xmm0,%%xmm1 \n" - "movhlps %%xmm6,%%xmm7 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm6 \n" - "punpcklbw %%xmm5,%%xmm7 \n" - "paddusw %%xmm6,%%xmm0 \n" - "paddusw %%xmm7,%%xmm1 \n" - MEMOPREG(movdqa,0x00,0,3,2,xmm6) // movdqa (%0,%3,2),%%xmm6 - "lea " MEMLEA(0x10,0) ",%0 \n" - "movhlps %%xmm6,%%xmm7 \n" - "punpcklbw %%xmm5,%%xmm6 \n" - "punpcklbw %%xmm5,%%xmm7 \n" - "paddusw %%xmm6,%%xmm0 \n" - "paddusw %%xmm7,%%xmm1 \n" - "movdqa %%xmm0,%%xmm6 \n" - "psrldq $0x2,%%xmm0 \n" - "paddusw %%xmm0,%%xmm6 \n" - "psrldq $0x2,%%xmm0 \n" - "paddusw %%xmm0,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "movdqa %%xmm1,%%xmm7 \n" - "psrldq $0x2,%%xmm1 \n" - "paddusw %%xmm1,%%xmm7 \n" - "psrldq $0x2,%%xmm1 \n" - "paddusw %%xmm1,%%xmm7 \n" - "pshufb %%xmm3,%%xmm7 \n" - "paddusw %%xmm7,%%xmm6 \n" - "pmulhuw %%xmm4,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "sub $0x6,%2 \n" - "movd %%xmm6," MEMACCESS(1) " \n" - "psrlq $0x10,%%xmm6 \n" - "movd %%xmm6," MEMACCESS2(0x2,1) " \n" - "lea " MEMLEA(0x6,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" -#endif - ); -} - -void ScaleAddRows_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, int src_height) { - int tmp_height = 0; - intptr_t tmp_src = 0; - asm volatile ( - "pxor %%xmm4,%%xmm4 \n" - "sub $0x1,%5 \n" - - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "mov %0,%3 \n" - "add %6,%0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm4,%%xmm0 \n" - "punpckhbw %%xmm4,%%xmm1 \n" - "mov %5,%2 \n" - "test %2,%2 \n" - "je 3f \n" - - LABELALIGN - "2: \n" - "movdqa " MEMACCESS(0) ",%%xmm2 \n" - "add %6,%0 \n" - "movdqa %%xmm2,%%xmm3 \n" - "punpcklbw %%xmm4,%%xmm2 \n" - "punpckhbw %%xmm4,%%xmm3 \n" - "paddusw %%xmm2,%%xmm0 \n" - "paddusw %%xmm3,%%xmm1 \n" - "sub $0x1,%2 \n" - "jg 2b \n" - - LABELALIGN - "3: \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,1) " \n" - "lea " MEMLEA(0x10,3) ",%0 \n" - "lea " MEMLEA(0x20,1) ",%1 \n" - "sub $0x10,%4 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(tmp_height), // %2 - "+r"(tmp_src), // %3 - "+r"(src_width), // %4 - "+rm"(src_height) // %5 - : "rm"((intptr_t)(src_stride)) // %6 - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" -#endif - ); -} - -// Bilinear column filtering. SSSE3 version. -void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, - int dst_width, int x, int dx) { - intptr_t x0 = 0, x1 = 0, temp_pixel = 0; - asm volatile ( - "movd %6,%%xmm2 \n" - "movd %7,%%xmm3 \n" - "movl $0x04040000,%k2 \n" - "movd %k2,%%xmm5 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrlw $0x9,%%xmm6 \n" - "pextrw $0x1,%%xmm2,%k3 \n" - "subl $0x2,%5 \n" - "jl 29f \n" - "movdqa %%xmm2,%%xmm0 \n" - "paddd %%xmm3,%%xmm0 \n" - "punpckldq %%xmm0,%%xmm2 \n" - "punpckldq %%xmm3,%%xmm3 \n" - "paddd %%xmm3,%%xmm3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - - LABELALIGN - "2: \n" - "movdqa %%xmm2,%%xmm1 \n" - "paddd %%xmm3,%%xmm2 \n" - MEMOPARG(movzwl,0x00,1,3,1,k2) // movzwl (%1,%3,1),%k2 - "movd %k2,%%xmm0 \n" - "psrlw $0x9,%%xmm1 \n" - BUNDLEALIGN - MEMOPARG(movzwl,0x00,1,4,1,k2) // movzwl (%1,%4,1),%k2 - "movd %k2,%%xmm4 \n" - "pshufb %%xmm5,%%xmm1 \n" - "punpcklwd %%xmm4,%%xmm0 \n" - "pxor %%xmm6,%%xmm1 \n" - "pmaddubsw %%xmm1,%%xmm0 \n" - "pextrw $0x1,%%xmm2,%k3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - "psrlw $0x7,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movd %%xmm0,%k2 \n" - "mov %w2," MEMACCESS(0) " \n" - "lea " MEMLEA(0x2,0) ",%0 \n" - "sub $0x2,%5 \n" - "jge 2b \n" - - LABELALIGN - "29: \n" - "addl $0x1,%5 \n" - "jl 99f \n" - MEMOPARG(movzwl,0x00,1,3,1,k2) // movzwl (%1,%3,1),%k2 - "movd %k2,%%xmm0 \n" - "psrlw $0x9,%%xmm2 \n" - "pshufb %%xmm5,%%xmm2 \n" - "pxor %%xmm6,%%xmm2 \n" - "pmaddubsw %%xmm2,%%xmm0 \n" - "psrlw $0x7,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movd %%xmm0,%k2 \n" - "mov %b2," MEMACCESS(0) " \n" - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+a"(temp_pixel), // %2 - "+r"(x0), // %3 - "+r"(x1), // %4 - "+rm"(dst_width) // %5 - : "rm"(x), // %6 - "rm"(dx) // %7 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -// Reads 4 pixels, duplicates them and writes 8 pixels. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr, - int dst_width, int x, int dx) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - "sub $0x20,%2 \n" - "movdqa %%xmm0," MEMACCESS(0) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,0) " \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "jg 1b \n" - - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void ScaleARGBRowDown2_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "shufps $0xdd,%%xmm1,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "movdqa %%xmm0,%%xmm2 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm2 \n" - "pavgb %%xmm2,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, - uint8* dst_argb, int dst_width) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(0) ",%%xmm0 \n" - "movdqa " MEMACCESS2(0x10,0) ",%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movdqa,0x00,0,3,1,xmm2) // movdqa (%0,%3,1),%%xmm2 - MEMOPREG(movdqa,0x10,0,3,1,xmm3) // movdqa 0x10(%0,%3,1),%%xmm3 - "lea " MEMLEA(0x20,0) ",%0 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm2 \n" - "pavgb %%xmm2,%%xmm0 \n" - "sub $0x4,%2 \n" - "movdqa %%xmm0," MEMACCESS(1) " \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_argb), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t)(src_stride)) // %3 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3" -#endif - ); -} - -// Reads 4 pixels at a time. -// Alignment requirement: dst_argb 16 byte aligned. -void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, - int src_stepx, - uint8* dst_argb, int dst_width) { - intptr_t src_stepx_x4 = (intptr_t)(src_stepx); - intptr_t src_stepx_x12 = 0; - asm volatile ( - "lea " MEMLEA3(0x00,1,4) ",%1 \n" - "lea " MEMLEA4(0x00,1,1,2) ",%4 \n" - LABELALIGN - "1: \n" - "movd " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movd,0x00,0,1,1,xmm1) // movd (%0,%1,1),%%xmm1 - "punpckldq %%xmm1,%%xmm0 \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,0,1,2,xmm2) // movd (%0,%1,2),%%xmm2 - MEMOPREG(movd,0x00,0,4,1,xmm3) // movd (%0,%4,1),%%xmm3 - "lea " MEMLEA4(0x00,0,1,4) ",%0 \n" - "punpckldq %%xmm3,%%xmm2 \n" - "punpcklqdq %%xmm2,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(src_stepx_x4), // %1 - "+r"(dst_argb), // %2 - "+r"(dst_width), // %3 - "+r"(src_stepx_x12) // %4 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3" -#endif - ); -} - -// Blends four 2x2 to 4x1. -// Alignment requirement: dst_argb 16 byte aligned. -void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, - ptrdiff_t src_stride, int src_stepx, - uint8* dst_argb, int dst_width) { - intptr_t src_stepx_x4 = (intptr_t)(src_stepx); - intptr_t src_stepx_x12 = 0; - intptr_t row1 = (intptr_t)(src_stride); - asm volatile ( - "lea " MEMLEA3(0x00,1,4) ",%1 \n" - "lea " MEMLEA4(0x00,1,1,2) ",%4 \n" - "lea " MEMLEA4(0x00,0,5,1) ",%5 \n" - - LABELALIGN - "1: \n" - "movq " MEMACCESS(0) ",%%xmm0 \n" - MEMOPREG(movhps,0x00,0,1,1,xmm0) // movhps (%0,%1,1),%%xmm0 - MEMOPREG(movq,0x00,0,1,2,xmm1) // movq (%0,%1,2),%%xmm1 - BUNDLEALIGN - MEMOPREG(movhps,0x00,0,4,1,xmm1) // movhps (%0,%4,1),%%xmm1 - "lea " MEMLEA4(0x00,0,1,4) ",%0 \n" - "movq " MEMACCESS(5) ",%%xmm2 \n" - BUNDLEALIGN - MEMOPREG(movhps,0x00,5,1,1,xmm2) // movhps (%5,%1,1),%%xmm2 - MEMOPREG(movq,0x00,5,1,2,xmm3) // movq (%5,%1,2),%%xmm3 - MEMOPREG(movhps,0x00,5,4,1,xmm3) // movhps (%5,%4,1),%%xmm3 - "lea " MEMLEA4(0x00,5,1,4) ",%5 \n" - "pavgb %%xmm2,%%xmm0 \n" - "pavgb %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm2 \n" - "pavgb %%xmm2,%%xmm0 \n" - "sub $0x4,%3 \n" - "movdqa %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(src_stepx_x4), // %1 - "+r"(dst_argb), // %2 - "+rm"(dst_width), // %3 - "+r"(src_stepx_x12), // %4 - "+r"(row1) // %5 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3" -#endif - ); -} - -void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, - int dst_width, int x, int dx) { - intptr_t x0 = 0, x1 = 0; - asm volatile ( - "movd %5,%%xmm2 \n" - "movd %6,%%xmm3 \n" - "pshufd $0x0,%%xmm2,%%xmm2 \n" - "pshufd $0x11,%%xmm3,%%xmm0 \n" - "paddd %%xmm0,%%xmm2 \n" - "paddd %%xmm3,%%xmm3 \n" - "pshufd $0x5,%%xmm3,%%xmm0 \n" - "paddd %%xmm0,%%xmm2 \n" - "paddd %%xmm3,%%xmm3 \n" - "pshufd $0x0,%%xmm3,%%xmm3 \n" - "pextrw $0x1,%%xmm2,%k0 \n" - "pextrw $0x3,%%xmm2,%k1 \n" - "cmp $0x0,%4 \n" - "jl 99f \n" - "sub $0x4,%4 \n" - "jl 49f \n" - - LABELALIGN - "40: \n" - MEMOPREG(movd,0x00,3,0,4,xmm0) // movd (%3,%0,4),%%xmm0 - MEMOPREG(movd,0x00,3,1,4,xmm1) // movd (%3,%1,4),%%xmm1 - "pextrw $0x5,%%xmm2,%k0 \n" - "pextrw $0x7,%%xmm2,%k1 \n" - "paddd %%xmm3,%%xmm2 \n" - "punpckldq %%xmm1,%%xmm0 \n" - MEMOPREG(movd,0x00,3,0,4,xmm1) // movd (%3,%0,4),%%xmm1 - MEMOPREG(movd,0x00,3,1,4,xmm4) // movd (%3,%1,4),%%xmm4 - "pextrw $0x1,%%xmm2,%k0 \n" - "pextrw $0x3,%%xmm2,%k1 \n" - "punpckldq %%xmm4,%%xmm1 \n" - "punpcklqdq %%xmm1,%%xmm0 \n" - "sub $0x4,%4 \n" - "movdqu %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x10,2) ",%2 \n" - "jge 40b \n" - - "49: \n" - "test $0x2,%4 \n" - "je 29f \n" - BUNDLEALIGN - MEMOPREG(movd,0x00,3,0,4,xmm0) // movd (%3,%0,4),%%xmm0 - MEMOPREG(movd,0x00,3,1,4,xmm1) // movd (%3,%1,4),%%xmm1 - "pextrw $0x5,%%xmm2,%k0 \n" - "punpckldq %%xmm1,%%xmm0 \n" - "movq %%xmm0," MEMACCESS(2) " \n" - "lea " MEMLEA(0x8,2) ",%2 \n" - "29: \n" - "test $0x1,%4 \n" - "je 99f \n" - MEMOPREG(movd,0x00,3,0,4,xmm0) // movd (%3,%0,4),%%xmm0 - "movd %%xmm0," MEMACCESS(2) " \n" - "99: \n" - : "+a"(x0), // %0 - "+d"(x1), // %1 - "+r"(dst_argb), // %2 - "+r"(src_argb), // %3 - "+r"(dst_width) // %4 - : "rm"(x), // %5 - "rm"(dx) // %6 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" -#endif - ); -} - -// Reads 4 pixels, duplicates them and writes 8 pixels. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, - int dst_width, int x, int dx) { - asm volatile ( - LABELALIGN - "1: \n" - "movdqa " MEMACCESS(1) ",%%xmm0 \n" - "lea " MEMLEA(0x10,1) ",%1 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpckldq %%xmm0,%%xmm0 \n" - "punpckhdq %%xmm1,%%xmm1 \n" - "sub $0x8,%2 \n" - "movdqa %%xmm0," MEMACCESS(0) " \n" - "movdqa %%xmm1," MEMACCESS2(0x10,0) " \n" - "lea " MEMLEA(0x20,0) ",%0 \n" - "jg 1b \n" - - : "+r"(dst_argb), // %0 - "+r"(src_argb), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1" -#endif - ); -} - -// Shuffle table for arranging 2 pixels into pairs for pmaddubsw -static uvec8 kShuffleColARGB = { - 0u, 4u, 1u, 5u, 2u, 6u, 3u, 7u, // bbggrraa 1st pixel - 8u, 12u, 9u, 13u, 10u, 14u, 11u, 15u // bbggrraa 2nd pixel -}; - -// Shuffle table for duplicating 2 fractions into 8 bytes each -static uvec8 kShuffleFractions = { - 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, -}; - -// Bilinear row filtering combines 4x2 -> 4x1. SSSE3 version -void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, - int dst_width, int x, int dx) { - intptr_t x0 = 0, x1 = 0; - asm volatile ( - "movdqa %0,%%xmm4 \n" - "movdqa %1,%%xmm5 \n" - : - : "m"(kShuffleColARGB), // %0 - "m"(kShuffleFractions) // %1 - ); - - asm volatile ( - "movd %5,%%xmm2 \n" - "movd %6,%%xmm3 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrlw $0x9,%%xmm6 \n" - "pextrw $0x1,%%xmm2,%k3 \n" - "sub $0x2,%2 \n" - "jl 29f \n" - "movdqa %%xmm2,%%xmm0 \n" - "paddd %%xmm3,%%xmm0 \n" - "punpckldq %%xmm0,%%xmm2 \n" - "punpckldq %%xmm3,%%xmm3 \n" - "paddd %%xmm3,%%xmm3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - - LABELALIGN - "2: \n" - "movdqa %%xmm2,%%xmm1 \n" - "paddd %%xmm3,%%xmm2 \n" - MEMOPREG(movq,0x00,1,3,4,xmm0) // movq (%1,%3,4),%%xmm0 - "psrlw $0x9,%%xmm1 \n" - BUNDLEALIGN - MEMOPREG(movhps,0x00,1,4,4,xmm0) // movhps (%1,%4,4),%%xmm0 - "pshufb %%xmm5,%%xmm1 \n" - "pshufb %%xmm4,%%xmm0 \n" - "pxor %%xmm6,%%xmm1 \n" - "pmaddubsw %%xmm1,%%xmm0 \n" - "psrlw $0x7,%%xmm0 \n" - "pextrw $0x1,%%xmm2,%k3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movq %%xmm0," MEMACCESS(0) " \n" - "lea " MEMLEA(0x8,0) ",%0 \n" - "sub $0x2,%2 \n" - "jge 2b \n" - - LABELALIGN - "29: \n" - "add $0x1,%2 \n" - "jl 99f \n" - "psrlw $0x9,%%xmm2 \n" - BUNDLEALIGN - MEMOPREG(movq,0x00,1,3,4,xmm0) // movq (%1,%3,4),%%xmm0 - "pshufb %%xmm5,%%xmm2 \n" - "pshufb %%xmm4,%%xmm0 \n" - "pxor %%xmm6,%%xmm2 \n" - "pmaddubsw %%xmm2,%%xmm0 \n" - "psrlw $0x7,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movd %%xmm0," MEMACCESS(0) " \n" - - LABELALIGN - "99: \n" - : "+r"(dst_argb), // %0 - "+r"(src_argb), // %1 - "+rm"(dst_width), // %2 - "+r"(x0), // %3 - "+r"(x1) // %4 - : "rm"(x), // %5 - "rm"(dx) // %6 - : "memory", "cc" -#if defined(__native_client__) && defined(__x86_64__) - , "r14" -#endif -#if defined(__SSE2__) - , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6" -#endif - ); -} - -// Divide num by div and return as 16.16 fixed point result. -int FixedDiv_X86(int num, int div) { - asm volatile ( - "cdq \n" - "shld $0x10,%%eax,%%edx \n" - "shl $0x10,%%eax \n" - "idiv %1 \n" - "mov %0, %%eax \n" - : "+a"(num) // %0 - : "c"(div) // %1 - : "memory", "cc", "edx" - ); - return num; -} - -// Divide num - 1 by div - 1 and return as 16.16 fixed point result. -int FixedDiv1_X86(int num, int div) { - asm volatile ( - "cdq \n" - "shld $0x10,%%eax,%%edx \n" - "shl $0x10,%%eax \n" - "sub $0x10001,%%eax \n" - "sbb $0x0,%%edx \n" - "sub $0x1,%1 \n" - "idiv %1 \n" - "mov %0, %%eax \n" - : "+a"(num) // %0 - : "c"(div) // %1 - : "memory", "cc", "edx" - ); - return num; -} - -#endif // defined(__x86_64__) || defined(__i386__) - -#ifdef __cplusplus -} // extern "C" -} // namespace libyuv -#endif diff --git a/TMessagesProj/jni/libyuv/source/scale_win.cc b/TMessagesProj/jni/libyuv/source/scale_win.cc index 840b9738..5ab4fa0c 100644 --- a/TMessagesProj/jni/libyuv/source/scale_win.cc +++ b/TMessagesProj/jni/libyuv/source/scale_win.cc @@ -9,14 +9,15 @@ */ #include "libyuv/row.h" +#include "libyuv/scale_row.h" #ifdef __cplusplus namespace libyuv { extern "C" { #endif -// This module is for Visual C x86. -#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) +// This module is for 32 bit Visual C x86 and clangcl +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) // Offsets for source bytes 0 to 9 static uvec8 kShuf0 = @@ -93,9 +94,111 @@ static uvec16 kScaleAb2 = { 65536 / 3, 65536 / 3, 65536 / 2, 65536 / 3, 65536 / 3, 65536 / 2, 0, 0 }; // Reads 32 pixels, throws half away and writes 16 pixels. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +__declspec(naked) +void ScaleRowDown2_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) { + __asm { + mov eax, [esp + 4] // src_ptr + // src_stride ignored + mov edx, [esp + 12] // dst_ptr + mov ecx, [esp + 16] // dst_width + + wloop: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + lea eax, [eax + 32] + psrlw xmm0, 8 // isolate odd pixels. + psrlw xmm1, 8 + packuswb xmm0, xmm1 + movdqu [edx], xmm0 + lea edx, [edx + 16] + sub ecx, 16 + jg wloop + + ret + } +} + +// Blends 32x1 rectangle to 16x1. +__declspec(naked) +void ScaleRowDown2Linear_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) { + __asm { + mov eax, [esp + 4] // src_ptr + // src_stride + mov edx, [esp + 12] // dst_ptr + mov ecx, [esp + 16] // dst_width + + pcmpeqb xmm4, xmm4 // constant 0x0101 + psrlw xmm4, 15 + packuswb xmm4, xmm4 + pxor xmm5, xmm5 // constant 0 + + wloop: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + lea eax, [eax + 32] + pmaddubsw xmm0, xmm4 // horizontal add + pmaddubsw xmm1, xmm4 + pavgw xmm0, xmm5 // (x + 1) / 2 + pavgw xmm1, xmm5 + packuswb xmm0, xmm1 + movdqu [edx], xmm0 + lea edx, [edx + 16] + sub ecx, 16 + jg wloop + + ret + } +} + +// Blends 32x2 rectangle to 16x1. +__declspec(naked) +void ScaleRowDown2Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) { + __asm { + push esi + mov eax, [esp + 4 + 4] // src_ptr + mov esi, [esp + 4 + 8] // src_stride + mov edx, [esp + 4 + 12] // dst_ptr + mov ecx, [esp + 4 + 16] // dst_width + + pcmpeqb xmm4, xmm4 // constant 0x0101 + psrlw xmm4, 15 + packuswb xmm4, xmm4 + pxor xmm5, xmm5 // constant 0 + + wloop: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + esi] + movdqu xmm3, [eax + esi + 16] + lea eax, [eax + 32] + pmaddubsw xmm0, xmm4 // horizontal add + pmaddubsw xmm1, xmm4 + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + paddw xmm0, xmm2 // vertical add + paddw xmm1, xmm3 + psrlw xmm0, 1 + psrlw xmm1, 1 + pavgw xmm0, xmm5 // (x + 1) / 2 + pavgw xmm1, xmm5 + packuswb xmm0, xmm1 + movdqu [edx], xmm0 + lea edx, [edx + 16] + sub ecx, 16 + jg wloop + + pop esi + ret + } +} + +#ifdef HAS_SCALEROWDOWN2_AVX2 +// Reads 64 pixels, throws half away and writes 32 pixels. +__declspec(naked) +void ScaleRowDown2_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { mov eax, [esp + 4] // src_ptr @@ -103,222 +206,110 @@ void ScaleRowDown2_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, mov edx, [esp + 12] // dst_ptr mov ecx, [esp + 16] // dst_width - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - psrlw xmm0, 8 // isolate odd pixels. - psrlw xmm1, 8 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg wloop + vmovdqu ymm0, [eax] + vmovdqu ymm1, [eax + 32] + lea eax, [eax + 64] + vpsrlw ymm0, ymm0, 8 // isolate odd pixels. + vpsrlw ymm1, ymm1, 8 + vpackuswb ymm0, ymm0, ymm1 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vmovdqu [edx], ymm0 + lea edx, [edx + 32] + sub ecx, 32 + jg wloop + vzeroupper ret } } -// Blends 32x1 rectangle to 16x1. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2Linear_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +// Blends 64x1 rectangle to 32x1. +__declspec(naked) +void ScaleRowDown2Linear_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { - mov eax, [esp + 4] // src_ptr - // src_stride - mov edx, [esp + 12] // dst_ptr - mov ecx, [esp + 16] // dst_width - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 + mov eax, [esp + 4] // src_ptr + // src_stride + mov edx, [esp + 12] // dst_ptr + mov ecx, [esp + 16] // dst_width + + vpcmpeqb ymm4, ymm4, ymm4 // '1' constant, 8b + vpsrlw ymm4, ymm4, 15 + vpackuswb ymm4, ymm4, ymm4 + vpxor ymm5, ymm5, ymm5 // constant 0 - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - lea eax, [eax + 32] - - movdqa xmm2, xmm0 // average columns (32 to 16 pixels) - psrlw xmm0, 8 - movdqa xmm3, xmm1 - psrlw xmm1, 8 - pand xmm2, xmm5 - pand xmm3, xmm5 - pavgw xmm0, xmm2 - pavgw xmm1, xmm3 - packuswb xmm0, xmm1 - - sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg wloop + vmovdqu ymm0, [eax] + vmovdqu ymm1, [eax + 32] + lea eax, [eax + 64] + vpmaddubsw ymm0, ymm0, ymm4 // horizontal add + vpmaddubsw ymm1, ymm1, ymm4 + vpavgw ymm0, ymm0, ymm5 // (x + 1) / 2 + vpavgw ymm1, ymm1, ymm5 + vpackuswb ymm0, ymm0, ymm1 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vmovdqu [edx], ymm0 + lea edx, [edx + 32] + sub ecx, 32 + jg wloop + vzeroupper ret } } -// Blends 32x2 rectangle to 16x1. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +// For rounding, average = (sum + 2) / 4 +// becomes average((sum >> 1), 0) +// Blends 64x2 rectangle to 32x1. +__declspec(naked) +void ScaleRowDown2Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { - push esi - mov eax, [esp + 4 + 4] // src_ptr - mov esi, [esp + 4 + 8] // src_stride - mov edx, [esp + 4 + 12] // dst_ptr - mov ecx, [esp + 4 + 16] // dst_width - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 + push esi + mov eax, [esp + 4 + 4] // src_ptr + mov esi, [esp + 4 + 8] // src_stride + mov edx, [esp + 4 + 12] // dst_ptr + mov ecx, [esp + 4 + 16] // dst_width + + vpcmpeqb ymm4, ymm4, ymm4 // '1' constant, 8b + vpsrlw ymm4, ymm4, 15 + vpackuswb ymm4, ymm4, ymm4 + vpxor ymm5, ymm5, ymm5 // constant 0 - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + esi] - movdqa xmm3, [eax + esi + 16] - lea eax, [eax + 32] - pavgb xmm0, xmm2 // average rows - pavgb xmm1, xmm3 + vmovdqu ymm0, [eax] + vmovdqu ymm1, [eax + 32] + vmovdqu ymm2, [eax + esi] + vmovdqu ymm3, [eax + esi + 32] + lea eax, [eax + 64] + vpmaddubsw ymm0, ymm0, ymm4 // horizontal add + vpmaddubsw ymm1, ymm1, ymm4 + vpmaddubsw ymm2, ymm2, ymm4 + vpmaddubsw ymm3, ymm3, ymm4 + vpaddw ymm0, ymm0, ymm2 // vertical add + vpaddw ymm1, ymm1, ymm3 + vpsrlw ymm0, ymm0, 1 + vpsrlw ymm1, ymm1, 1 + vpavgw ymm0, ymm0, ymm5 // (x + 1) / 2 + vpavgw ymm1, ymm1, ymm5 + vpackuswb ymm0, ymm0, ymm1 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vmovdqu [edx], ymm0 + lea edx, [edx + 32] + sub ecx, 32 + jg wloop - movdqa xmm2, xmm0 // average columns (32 to 16 pixels) - psrlw xmm0, 8 - movdqa xmm3, xmm1 - psrlw xmm1, 8 - pand xmm2, xmm5 - pand xmm3, xmm5 - pavgw xmm0, xmm2 - pavgw xmm1, xmm3 - packuswb xmm0, xmm1 - - sub ecx, 16 - movdqa [edx], xmm0 - lea edx, [edx + 16] - jg wloop - - pop esi - ret - } -} - -// Reads 32 pixels, throws half away and writes 16 pixels. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - __asm { - mov eax, [esp + 4] // src_ptr - // src_stride ignored - mov edx, [esp + 12] // dst_ptr - mov ecx, [esp + 16] // dst_width - - align 4 - wloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - lea eax, [eax + 32] - psrlw xmm0, 8 // isolate odd pixels. - psrlw xmm1, 8 - packuswb xmm0, xmm1 - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg wloop - - ret - } -} - -// Blends 32x1 rectangle to 16x1. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2Linear_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - __asm { - mov eax, [esp + 4] // src_ptr - // src_stride - mov edx, [esp + 12] // dst_ptr - mov ecx, [esp + 16] // dst_width - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - - align 4 - wloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - lea eax, [eax + 32] - - movdqa xmm2, xmm0 // average columns (32 to 16 pixels) - psrlw xmm0, 8 - movdqa xmm3, xmm1 - psrlw xmm1, 8 - pand xmm2, xmm5 - pand xmm3, xmm5 - pavgw xmm0, xmm2 - pavgw xmm1, xmm3 - packuswb xmm0, xmm1 - - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg wloop - - ret - } -} - -// Blends 32x2 rectangle to 16x1. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown2Box_Unaligned_SSE2(const uint8* src_ptr, - ptrdiff_t src_stride, - uint8* dst_ptr, int dst_width) { - __asm { - push esi - mov eax, [esp + 4 + 4] // src_ptr - mov esi, [esp + 4 + 8] // src_stride - mov edx, [esp + 4 + 12] // dst_ptr - mov ecx, [esp + 4 + 16] // dst_width - pcmpeqb xmm5, xmm5 // generate mask 0x00ff00ff - psrlw xmm5, 8 - - align 4 - wloop: - movdqu xmm0, [eax] - movdqu xmm1, [eax + 16] - movdqu xmm2, [eax + esi] - movdqu xmm3, [eax + esi + 16] - lea eax, [eax + 32] - pavgb xmm0, xmm2 // average rows - pavgb xmm1, xmm3 - - movdqa xmm2, xmm0 // average columns (32 to 16 pixels) - psrlw xmm0, 8 - movdqa xmm3, xmm1 - psrlw xmm1, 8 - pand xmm2, xmm5 - pand xmm3, xmm5 - pavgw xmm0, xmm2 - pavgw xmm1, xmm3 - packuswb xmm0, xmm1 - - sub ecx, 16 - movdqu [edx], xmm0 - lea edx, [edx + 16] - jg wloop - - pop esi + pop esi + vzeroupper ret } } +#endif // HAS_SCALEROWDOWN2_AVX2 // Point samples 32 pixels to 8 pixels. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown4_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +__declspec(naked) +void ScaleRowDown4_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { mov eax, [esp + 4] // src_ptr @@ -329,19 +320,18 @@ void ScaleRowDown4_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, psrld xmm5, 24 pslld xmm5, 16 - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] lea eax, [eax + 32] pand xmm0, xmm5 pand xmm1, xmm5 packuswb xmm0, xmm1 psrlw xmm0, 8 packuswb xmm0, xmm0 - sub ecx, 8 movq qword ptr [edx], xmm0 lea edx, [edx + 8] + sub ecx, 8 jg wloop ret @@ -349,9 +339,8 @@ void ScaleRowDown4_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, } // Blends 32x4 rectangle to 8x1. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned. -__declspec(naked) __declspec(align(16)) -void ScaleRowDown4Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, +__declspec(naked) +void ScaleRowDown4Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { push esi @@ -361,46 +350,43 @@ void ScaleRowDown4Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, mov edx, [esp + 8 + 12] // dst_ptr mov ecx, [esp + 8 + 16] // dst_width lea edi, [esi + esi * 2] // src_stride * 3 - pcmpeqb xmm7, xmm7 // generate mask 0x00ff00ff - psrlw xmm7, 8 + pcmpeqb xmm4, xmm4 // constant 0x0101 + psrlw xmm4, 15 + movdqa xmm5, xmm4 + packuswb xmm4, xmm4 + psllw xmm5, 3 // constant 0x0008 - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + esi] - movdqa xmm3, [eax + esi + 16] - pavgb xmm0, xmm2 // average rows - pavgb xmm1, xmm3 - movdqa xmm2, [eax + esi * 2] - movdqa xmm3, [eax + esi * 2 + 16] - movdqa xmm4, [eax + edi] - movdqa xmm5, [eax + edi + 16] + movdqu xmm0, [eax] // average rows + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + esi] + movdqu xmm3, [eax + esi + 16] + pmaddubsw xmm0, xmm4 // horizontal add + pmaddubsw xmm1, xmm4 + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + paddw xmm0, xmm2 // vertical add rows 0, 1 + paddw xmm1, xmm3 + movdqu xmm2, [eax + esi * 2] + movdqu xmm3, [eax + esi * 2 + 16] + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + paddw xmm0, xmm2 // add row 2 + paddw xmm1, xmm3 + movdqu xmm2, [eax + edi] + movdqu xmm3, [eax + edi + 16] lea eax, [eax + 32] - pavgb xmm2, xmm4 - pavgb xmm3, xmm5 - pavgb xmm0, xmm2 - pavgb xmm1, xmm3 - - movdqa xmm2, xmm0 // average columns (32 to 16 pixels) - psrlw xmm0, 8 - movdqa xmm3, xmm1 - psrlw xmm1, 8 - pand xmm2, xmm7 - pand xmm3, xmm7 - pavgw xmm0, xmm2 - pavgw xmm1, xmm3 - packuswb xmm0, xmm1 - - movdqa xmm2, xmm0 // average columns (16 to 8 pixels) - psrlw xmm0, 8 - pand xmm2, xmm7 - pavgw xmm0, xmm2 + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + paddw xmm0, xmm2 // add row 3 + paddw xmm1, xmm3 + phaddw xmm0, xmm1 + paddw xmm0, xmm5 // + 8 for round + psrlw xmm0, 4 // /16 for average of 4 * 4 packuswb xmm0, xmm0 - - sub ecx, 8 movq qword ptr [edx], xmm0 lea edx, [edx + 8] + sub ecx, 8 jg wloop pop edi @@ -409,13 +395,106 @@ void ScaleRowDown4Box_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, } } +#ifdef HAS_SCALEROWDOWN4_AVX2 +// Point samples 64 pixels to 16 pixels. +__declspec(naked) +void ScaleRowDown4_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) { + __asm { + mov eax, [esp + 4] // src_ptr + // src_stride ignored + mov edx, [esp + 12] // dst_ptr + mov ecx, [esp + 16] // dst_width + vpcmpeqb ymm5, ymm5, ymm5 // generate mask 0x00ff0000 + vpsrld ymm5, ymm5, 24 + vpslld ymm5, ymm5, 16 + + wloop: + vmovdqu ymm0, [eax] + vmovdqu ymm1, [eax + 32] + lea eax, [eax + 64] + vpand ymm0, ymm0, ymm5 + vpand ymm1, ymm1, ymm5 + vpackuswb ymm0, ymm0, ymm1 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vpsrlw ymm0, ymm0, 8 + vpackuswb ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vmovdqu [edx], xmm0 + lea edx, [edx + 16] + sub ecx, 16 + jg wloop + + vzeroupper + ret + } +} + +// Blends 64x4 rectangle to 16x1. +__declspec(naked) +void ScaleRowDown4Box_AVX2(const uint8* src_ptr, ptrdiff_t src_stride, + uint8* dst_ptr, int dst_width) { + __asm { + push esi + push edi + mov eax, [esp + 8 + 4] // src_ptr + mov esi, [esp + 8 + 8] // src_stride + mov edx, [esp + 8 + 12] // dst_ptr + mov ecx, [esp + 8 + 16] // dst_width + lea edi, [esi + esi * 2] // src_stride * 3 + vpcmpeqb ymm4, ymm4, ymm4 // constant 0x0101 + vpsrlw ymm4, ymm4, 15 + vpsllw ymm5, ymm4, 3 // constant 0x0008 + vpackuswb ymm4, ymm4, ymm4 + + wloop: + vmovdqu ymm0, [eax] // average rows + vmovdqu ymm1, [eax + 32] + vmovdqu ymm2, [eax + esi] + vmovdqu ymm3, [eax + esi + 32] + vpmaddubsw ymm0, ymm0, ymm4 // horizontal add + vpmaddubsw ymm1, ymm1, ymm4 + vpmaddubsw ymm2, ymm2, ymm4 + vpmaddubsw ymm3, ymm3, ymm4 + vpaddw ymm0, ymm0, ymm2 // vertical add rows 0, 1 + vpaddw ymm1, ymm1, ymm3 + vmovdqu ymm2, [eax + esi * 2] + vmovdqu ymm3, [eax + esi * 2 + 32] + vpmaddubsw ymm2, ymm2, ymm4 + vpmaddubsw ymm3, ymm3, ymm4 + vpaddw ymm0, ymm0, ymm2 // add row 2 + vpaddw ymm1, ymm1, ymm3 + vmovdqu ymm2, [eax + edi] + vmovdqu ymm3, [eax + edi + 32] + lea eax, [eax + 64] + vpmaddubsw ymm2, ymm2, ymm4 + vpmaddubsw ymm3, ymm3, ymm4 + vpaddw ymm0, ymm0, ymm2 // add row 3 + vpaddw ymm1, ymm1, ymm3 + vphaddw ymm0, ymm0, ymm1 // mutates + vpermq ymm0, ymm0, 0xd8 // unmutate vphaddw + vpaddw ymm0, ymm0, ymm5 // + 8 for round + vpsrlw ymm0, ymm0, 4 // /32 for average of 4 * 4 + vpackuswb ymm0, ymm0, ymm0 + vpermq ymm0, ymm0, 0xd8 // unmutate vpackuswb + vmovdqu [edx], xmm0 + lea edx, [edx + 16] + sub ecx, 16 + jg wloop + + pop edi + pop esi + vzeroupper + ret + } +} +#endif // HAS_SCALEROWDOWN4_AVX2 + // Point samples 32 pixels to 24 pixels. // Produces three 8 byte values. For each 8 bytes, 16 bytes are read. // Then shuffled to do the scaling. -// Note that movdqa+palign may be better than movdqu. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { @@ -423,14 +502,13 @@ void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, // src_stride ignored mov edx, [esp + 12] // dst_ptr mov ecx, [esp + 16] // dst_width - movdqa xmm3, kShuf0 - movdqa xmm4, kShuf1 - movdqa xmm5, kShuf2 + movdqa xmm3, xmmword ptr kShuf0 + movdqa xmm4, xmmword ptr kShuf1 + movdqa xmm5, xmmword ptr kShuf2 - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] lea eax, [eax + 32] movdqa xmm2, xmm1 palignr xmm1, xmm0, 8 @@ -463,8 +541,7 @@ void ScaleRowDown34_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, // xmm7 kRound34 // Note that movdqa+palign may be better than movdqu. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -474,17 +551,16 @@ void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, mov esi, [esp + 4 + 8] // src_stride mov edx, [esp + 4 + 12] // dst_ptr mov ecx, [esp + 4 + 16] // dst_width - movdqa xmm2, kShuf01 - movdqa xmm3, kShuf11 - movdqa xmm4, kShuf21 - movdqa xmm5, kMadd01 - movdqa xmm6, kMadd11 - movdqa xmm7, kRound34 + movdqa xmm2, xmmword ptr kShuf01 + movdqa xmm3, xmmword ptr kShuf11 + movdqa xmm4, xmmword ptr kShuf21 + movdqa xmm5, xmmword ptr kMadd01 + movdqa xmm6, xmmword ptr kMadd11 + movdqa xmm7, xmmword ptr kRound34 - align 4 wloop: - movdqa xmm0, [eax] // pixels 0..7 - movdqa xmm1, [eax + esi] + movdqu xmm0, [eax] // pixels 0..7 + movdqu xmm1, [eax + esi] pavgb xmm0, xmm1 pshufb xmm0, xmm2 pmaddubsw xmm0, xmm5 @@ -501,19 +577,19 @@ void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, psrlw xmm0, 2 packuswb xmm0, xmm0 movq qword ptr [edx + 8], xmm0 - movdqa xmm0, [eax + 16] // pixels 16..23 - movdqa xmm1, [eax + esi + 16] + movdqu xmm0, [eax + 16] // pixels 16..23 + movdqu xmm1, [eax + esi + 16] lea eax, [eax + 32] pavgb xmm0, xmm1 pshufb xmm0, xmm4 - movdqa xmm1, kMadd21 + movdqa xmm1, xmmword ptr kMadd21 pmaddubsw xmm0, xmm1 paddsw xmm0, xmm7 psrlw xmm0, 2 packuswb xmm0, xmm0 - sub ecx, 24 movq qword ptr [edx + 16], xmm0 lea edx, [edx + 24] + sub ecx, 24 jg wloop pop esi @@ -522,8 +598,7 @@ void ScaleRowDown34_1_Box_SSSE3(const uint8* src_ptr, } // Note that movdqa+palign may be better than movdqu. -// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -533,17 +608,16 @@ void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr, mov esi, [esp + 4 + 8] // src_stride mov edx, [esp + 4 + 12] // dst_ptr mov ecx, [esp + 4 + 16] // dst_width - movdqa xmm2, kShuf01 - movdqa xmm3, kShuf11 - movdqa xmm4, kShuf21 - movdqa xmm5, kMadd01 - movdqa xmm6, kMadd11 - movdqa xmm7, kRound34 + movdqa xmm2, xmmword ptr kShuf01 + movdqa xmm3, xmmword ptr kShuf11 + movdqa xmm4, xmmword ptr kShuf21 + movdqa xmm5, xmmword ptr kMadd01 + movdqa xmm6, xmmword ptr kMadd11 + movdqa xmm7, xmmword ptr kRound34 - align 4 wloop: - movdqa xmm0, [eax] // pixels 0..7 - movdqa xmm1, [eax + esi] + movdqu xmm0, [eax] // pixels 0..7 + movdqu xmm1, [eax + esi] pavgb xmm1, xmm0 pavgb xmm0, xmm1 pshufb xmm0, xmm2 @@ -562,20 +636,20 @@ void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr, psrlw xmm0, 2 packuswb xmm0, xmm0 movq qword ptr [edx + 8], xmm0 - movdqa xmm0, [eax + 16] // pixels 16..23 - movdqa xmm1, [eax + esi + 16] + movdqu xmm0, [eax + 16] // pixels 16..23 + movdqu xmm1, [eax + esi + 16] lea eax, [eax + 32] pavgb xmm1, xmm0 pavgb xmm0, xmm1 pshufb xmm0, xmm4 - movdqa xmm1, kMadd21 + movdqa xmm1, xmmword ptr kMadd21 pmaddubsw xmm0, xmm1 paddsw xmm0, xmm7 psrlw xmm0, 2 packuswb xmm0, xmm0 - sub ecx, 24 movq qword ptr [edx + 16], xmm0 lea edx, [edx+24] + sub ecx, 24 jg wloop pop esi @@ -586,7 +660,7 @@ void ScaleRowDown34_0_Box_SSSE3(const uint8* src_ptr, // 3/8 point sampler // Scale 32 pixels to 12 -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown38_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { __asm { @@ -594,23 +668,22 @@ void ScaleRowDown38_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, // src_stride ignored mov edx, [esp + 12] // dst_ptr mov ecx, [esp + 16] // dst_width - movdqa xmm4, kShuf38a - movdqa xmm5, kShuf38b + movdqa xmm4, xmmword ptr kShuf38a + movdqa xmm5, xmmword ptr kShuf38b - align 4 xloop: - movdqa xmm0, [eax] // 16 pixels -> 0,1,2,3,4,5 - movdqa xmm1, [eax + 16] // 16 pixels -> 6,7,8,9,10,11 + movdqu xmm0, [eax] // 16 pixels -> 0,1,2,3,4,5 + movdqu xmm1, [eax + 16] // 16 pixels -> 6,7,8,9,10,11 lea eax, [eax + 32] pshufb xmm0, xmm4 pshufb xmm1, xmm5 paddusb xmm0, xmm1 - sub ecx, 12 movq qword ptr [edx], xmm0 // write 12 pixels movhlps xmm1, xmm0 movd [edx + 8], xmm1 lea edx, [edx + 12] + sub ecx, 12 jg xloop ret @@ -618,7 +691,7 @@ void ScaleRowDown38_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, } // Scale 16x3 pixels to 6x1 with interpolation -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -628,15 +701,14 @@ void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, mov esi, [esp + 4 + 8] // src_stride mov edx, [esp + 4 + 12] // dst_ptr mov ecx, [esp + 4 + 16] // dst_width - movdqa xmm2, kShufAc - movdqa xmm3, kShufAc3 - movdqa xmm4, kScaleAc33 + movdqa xmm2, xmmword ptr kShufAc + movdqa xmm3, xmmword ptr kShufAc3 + movdqa xmm4, xmmword ptr kScaleAc33 pxor xmm5, xmm5 - align 4 xloop: - movdqa xmm0, [eax] // sum up 3 rows into xmm0/1 - movdqa xmm6, [eax + esi] + movdqu xmm0, [eax] // sum up 3 rows into xmm0/1 + movdqu xmm6, [eax + esi] movhlps xmm1, xmm0 movhlps xmm7, xmm6 punpcklbw xmm0, xmm5 @@ -645,7 +717,7 @@ void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, punpcklbw xmm7, xmm5 paddusw xmm0, xmm6 paddusw xmm1, xmm7 - movdqa xmm6, [eax + esi * 2] + movdqu xmm6, [eax + esi * 2] lea eax, [eax + 16] movhlps xmm7, xmm6 punpcklbw xmm6, xmm5 @@ -671,11 +743,11 @@ void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, pmulhuw xmm6, xmm4 // divide by 9,9,6, 9,9,6 packuswb xmm6, xmm6 - sub ecx, 6 movd [edx], xmm6 // write 6 pixels psrlq xmm6, 16 movd [edx + 2], xmm6 lea edx, [edx + 6] + sub ecx, 6 jg xloop pop esi @@ -684,7 +756,7 @@ void ScaleRowDown38_3_Box_SSSE3(const uint8* src_ptr, } // Scale 16x2 pixels to 6x1 with interpolation -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, ptrdiff_t src_stride, uint8* dst_ptr, int dst_width) { @@ -694,16 +766,16 @@ void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, mov esi, [esp + 4 + 8] // src_stride mov edx, [esp + 4 + 12] // dst_ptr mov ecx, [esp + 4 + 16] // dst_width - movdqa xmm2, kShufAb0 - movdqa xmm3, kShufAb1 - movdqa xmm4, kShufAb2 - movdqa xmm5, kScaleAb2 + movdqa xmm2, xmmword ptr kShufAb0 + movdqa xmm3, xmmword ptr kShufAb1 + movdqa xmm4, xmmword ptr kShufAb2 + movdqa xmm5, xmmword ptr kScaleAb2 - align 4 xloop: - movdqa xmm0, [eax] // average 2 rows into xmm0 - pavgb xmm0, [eax + esi] + movdqu xmm0, [eax] // average 2 rows into xmm0 + movdqu xmm1, [eax + esi] lea eax, [eax + 16] + pavgb xmm0, xmm1 movdqa xmm1, xmm0 // 16 pixels -> 0,1,2,3,4,5 of xmm1 pshufb xmm1, xmm2 @@ -716,11 +788,11 @@ void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, pmulhuw xmm1, xmm5 // divide by 3,3,2, 3,3,2 packuswb xmm1, xmm1 - sub ecx, 6 movd [edx], xmm1 // write 6 pixels psrlq xmm1, 16 movd [edx + 2], xmm1 lea edx, [edx + 6] + sub ecx, 6 jg xloop pop esi @@ -728,79 +800,68 @@ void ScaleRowDown38_2_Box_SSSE3(const uint8* src_ptr, } } -// Reads 16xN bytes and produces 16 shorts at a time. -// TODO(fbarchard): Make this handle 4xN bytes for any width ARGB. -__declspec(naked) __declspec(align(16)) -void ScaleAddRows_SSE2(const uint8* src_ptr, ptrdiff_t src_stride, - uint16* dst_ptr, int src_width, - int src_height) { +// Reads 16 bytes and accumulates to 16 shorts at a time. +__declspec(naked) +void ScaleAddRow_SSE2(const uint8* src_ptr, uint16* dst_ptr, int src_width) { __asm { - push esi - push edi - push ebx - push ebp - mov esi, [esp + 16 + 4] // src_ptr - mov edx, [esp + 16 + 8] // src_stride - mov edi, [esp + 16 + 12] // dst_ptr - mov ecx, [esp + 16 + 16] // dst_width - mov ebx, [esp + 16 + 20] // height - pxor xmm4, xmm4 - dec ebx + mov eax, [esp + 4] // src_ptr + mov edx, [esp + 8] // dst_ptr + mov ecx, [esp + 12] // src_width + pxor xmm5, xmm5 - align 4 + // sum rows xloop: - // first row - movdqa xmm0, [esi] - lea eax, [esi + edx] - movdqa xmm1, xmm0 - punpcklbw xmm0, xmm4 - punpckhbw xmm1, xmm4 - lea esi, [esi + 16] - mov ebp, ebx - test ebp, ebp - je ydone - - // sum remaining rows - align 4 - yloop: - movdqa xmm2, [eax] // read 16 pixels - lea eax, [eax + edx] // advance to next row - movdqa xmm3, xmm2 - punpcklbw xmm2, xmm4 - punpckhbw xmm3, xmm4 + movdqu xmm3, [eax] // read 16 bytes + lea eax, [eax + 16] + movdqu xmm0, [edx] // read 16 words from destination + movdqu xmm1, [edx + 16] + movdqa xmm2, xmm3 + punpcklbw xmm2, xmm5 + punpckhbw xmm3, xmm5 paddusw xmm0, xmm2 // sum 16 words paddusw xmm1, xmm3 - sub ebp, 1 - jg yloop - - align 4 - ydone: - movdqa [edi], xmm0 - movdqa [edi + 16], xmm1 - lea edi, [edi + 32] - + movdqu [edx], xmm0 // write 16 words to destination + movdqu [edx + 16], xmm1 + lea edx, [edx + 32] sub ecx, 16 jg xloop - - pop ebp - pop ebx - pop edi - pop esi ret } } -// Bilinear column filtering. SSSE3 version. -// TODO(fbarchard): Port to Neon -// TODO(fbarchard): Switch the following: -// xor ebx, ebx -// mov bx, word ptr [esi + eax] // 2 source x0 pixels -// To -// movzx ebx, word ptr [esi + eax] // 2 source x0 pixels -// when drmemory bug fixed. -// https://code.google.com/p/drmemory/issues/detail?id=1396 +#ifdef HAS_SCALEADDROW_AVX2 +// Reads 32 bytes and accumulates to 32 shorts at a time. +__declspec(naked) +void ScaleAddRow_AVX2(const uint8* src_ptr, uint16* dst_ptr, int src_width) { + __asm { + mov eax, [esp + 4] // src_ptr + mov edx, [esp + 8] // dst_ptr + mov ecx, [esp + 12] // src_width + vpxor ymm5, ymm5, ymm5 -__declspec(naked) __declspec(align(16)) + // sum rows + xloop: + vmovdqu ymm3, [eax] // read 32 bytes + lea eax, [eax + 32] + vpermq ymm3, ymm3, 0xd8 // unmutate for vpunpck + vpunpcklbw ymm2, ymm3, ymm5 + vpunpckhbw ymm3, ymm3, ymm5 + vpaddusw ymm0, ymm2, [edx] // sum 16 words + vpaddusw ymm1, ymm3, [edx + 32] + vmovdqu [edx], ymm0 // write 32 words to destination + vmovdqu [edx + 32], ymm1 + lea edx, [edx + 64] + sub ecx, 32 + jg xloop + + vzeroupper + ret + } +} +#endif // HAS_SCALEADDROW_AVX2 + +// Bilinear column filtering. SSSE3 version. +__declspec(naked) void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, int dst_width, int x, int dx) { __asm { @@ -828,7 +889,6 @@ void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, pextrw edx, xmm2, 3 // get x1 integer. preroll // 2 Pixel loop. - align 4 xloop2: movdqa xmm1, xmm2 // x0, x1 fractions. paddd xmm2, xmm3 // x += dx @@ -851,7 +911,6 @@ void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, sub ecx, 2 // 2 pixels jge xloop2 - align 4 xloop29: add ecx, 2 - 1 @@ -869,7 +928,6 @@ void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, movd ebx, xmm0 mov [edi], bl - align 4 xloop99: pop edi @@ -880,8 +938,7 @@ void ScaleFilterCols_SSSE3(uint8* dst_ptr, const uint8* src_ptr, } // Reads 16 pixels, duplicates them and writes 32 pixels. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr, int dst_width, int x, int dx) { __asm { @@ -889,17 +946,16 @@ void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr, mov eax, [esp + 8] // src_ptr mov ecx, [esp + 12] // dst_width - align 4 wloop: - movdqa xmm0, [eax] + movdqu xmm0, [eax] lea eax, [eax + 16] movdqa xmm1, xmm0 punpcklbw xmm0, xmm0 punpckhbw xmm1, xmm1 - sub ecx, 32 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 + movdqu [edx], xmm0 + movdqu [edx + 16], xmm1 lea edx, [edx + 32] + sub ecx, 32 jg wloop ret @@ -907,8 +963,7 @@ void ScaleColsUp2_SSE2(uint8* dst_ptr, const uint8* src_ptr, } // Reads 8 pixels, throws half away and writes 4 even pixels (0, 2, 4, 6) -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBRowDown2_SSE2(const uint8* src_argb, ptrdiff_t src_stride, uint8* dst_argb, int dst_width) { @@ -918,15 +973,14 @@ void ScaleARGBRowDown2_SSE2(const uint8* src_argb, mov edx, [esp + 12] // dst_argb mov ecx, [esp + 16] // dst_width - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] lea eax, [eax + 32] shufps xmm0, xmm1, 0xdd - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg wloop ret @@ -934,8 +988,7 @@ void ScaleARGBRowDown2_SSE2(const uint8* src_argb, } // Blends 8x1 rectangle to 4x1. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, ptrdiff_t src_stride, uint8* dst_argb, int dst_width) { @@ -945,18 +998,17 @@ void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, mov edx, [esp + 12] // dst_argb mov ecx, [esp + 16] // dst_width - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] lea eax, [eax + 32] movdqa xmm2, xmm0 shufps xmm0, xmm1, 0x88 // even pixels shufps xmm2, xmm1, 0xdd // odd pixels pavgb xmm0, xmm2 - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg wloop ret @@ -964,8 +1016,7 @@ void ScaleARGBRowDown2Linear_SSE2(const uint8* src_argb, } // Blends 8x2 rectangle to 4x1. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, ptrdiff_t src_stride, uint8* dst_argb, int dst_width) { @@ -976,12 +1027,11 @@ void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, mov edx, [esp + 4 + 12] // dst_argb mov ecx, [esp + 4 + 16] // dst_width - align 4 wloop: - movdqa xmm0, [eax] - movdqa xmm1, [eax + 16] - movdqa xmm2, [eax + esi] - movdqa xmm3, [eax + esi + 16] + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + esi] + movdqu xmm3, [eax + esi + 16] lea eax, [eax + 32] pavgb xmm0, xmm2 // average rows pavgb xmm1, xmm3 @@ -989,9 +1039,9 @@ void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, shufps xmm0, xmm1, 0x88 // even pixels shufps xmm2, xmm1, 0xdd // odd pixels pavgb xmm0, xmm2 - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg wloop pop esi @@ -1000,8 +1050,7 @@ void ScaleARGBRowDown2Box_SSE2(const uint8* src_argb, } // Reads 4 pixels at a time. -// Alignment requirement: dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, uint8* dst_argb, int dst_width) { @@ -1016,7 +1065,6 @@ void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, lea ebx, [ebx * 4] lea edi, [ebx + ebx * 2] - align 4 wloop: movd xmm0, [eax] movd xmm1, [eax + ebx] @@ -1026,9 +1074,9 @@ void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, lea eax, [eax + ebx * 4] punpckldq xmm2, xmm3 punpcklqdq xmm0, xmm2 - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg wloop pop edi @@ -1038,8 +1086,7 @@ void ScaleARGBRowDownEven_SSE2(const uint8* src_argb, ptrdiff_t src_stride, } // Blends four 2x2 to 4x1. -// Alignment requirement: dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, ptrdiff_t src_stride, int src_stepx, @@ -1057,7 +1104,6 @@ void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, lea ebx, [ebx * 4] lea edi, [ebx + ebx * 2] - align 4 wloop: movq xmm0, qword ptr [eax] // row0 4 pairs movhps xmm0, qword ptr [eax + ebx] @@ -1075,9 +1121,9 @@ void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, shufps xmm0, xmm1, 0x88 // even pixels shufps xmm2, xmm1, 0xdd // odd pixels pavgb xmm0, xmm2 - sub ecx, 4 - movdqa [edx], xmm0 + movdqu [edx], xmm0 lea edx, [edx + 16] + sub ecx, 4 jg wloop pop edi @@ -1088,7 +1134,7 @@ void ScaleARGBRowDownEvenBox_SSE2(const uint8* src_argb, } // Column scaling unfiltered. SSE2 version. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx) { __asm { @@ -1118,7 +1164,6 @@ void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, jl xloop49 // 4 Pixel loop. - align 4 xloop4: movd xmm0, [esi + eax * 4] // 1 source x0 pixels movd xmm1, [esi + edx * 4] // 1 source x1 pixels @@ -1133,12 +1178,11 @@ void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, pextrw edx, xmm2, 3 // get x1 integer. next iteration. punpckldq xmm1, xmm4 // x2 x3 punpcklqdq xmm0, xmm1 // x0 x1 x2 x3 - sub ecx, 4 // 4 pixels movdqu [edi], xmm0 lea edi, [edi + 16] + sub ecx, 4 // 4 pixels jge xloop4 - align 4 xloop49: test ecx, 2 je xloop29 @@ -1159,7 +1203,6 @@ void ScaleARGBCols_SSE2(uint8* dst_argb, const uint8* src_argb, // 1 Pixels. movd xmm0, [esi + eax * 4] // 1 source x2 pixels movd dword ptr [edi], xmm0 - align 4 xloop99: pop esi @@ -1182,7 +1225,7 @@ static uvec8 kShuffleFractions = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, }; -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx) { __asm { @@ -1193,8 +1236,8 @@ void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, mov ecx, [esp + 8 + 12] // dst_width movd xmm2, [esp + 8 + 16] // x movd xmm3, [esp + 8 + 20] // dx - movdqa xmm4, kShuffleColARGB - movdqa xmm5, kShuffleFractions + movdqa xmm4, xmmword ptr kShuffleColARGB + movdqa xmm5, xmmword ptr kShuffleFractions pcmpeqb xmm6, xmm6 // generate 0x007f for inverting fraction. psrlw xmm6, 9 pextrw eax, xmm2, 1 // get x0 integer. preroll @@ -1209,7 +1252,6 @@ void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, pextrw edx, xmm2, 3 // get x1 integer. preroll // 2 Pixel loop. - align 4 xloop2: movdqa xmm1, xmm2 // x0, x1 fractions. paddd xmm2, xmm3 // x += dx @@ -1229,7 +1271,6 @@ void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, sub ecx, 2 // 2 pixels jge xloop2 - align 4 xloop29: add ecx, 2 - 1 @@ -1246,7 +1287,6 @@ void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, packuswb xmm0, xmm0 // argb 8 bits, 1 pixel. movd [edi], xmm0 - align 4 xloop99: pop edi @@ -1256,8 +1296,7 @@ void ScaleARGBFilterCols_SSSE3(uint8* dst_argb, const uint8* src_argb, } // Reads 4 pixels, duplicates them and writes 8 pixels. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -__declspec(naked) __declspec(align(16)) +__declspec(naked) void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, int dst_width, int x, int dx) { __asm { @@ -1265,17 +1304,16 @@ void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, mov eax, [esp + 8] // src_argb mov ecx, [esp + 12] // dst_width - align 4 wloop: - movdqa xmm0, [eax] + movdqu xmm0, [eax] lea eax, [eax + 16] movdqa xmm1, xmm0 punpckldq xmm0, xmm0 punpckhdq xmm1, xmm1 - sub ecx, 8 - movdqa [edx], xmm0 - movdqa [edx + 16], xmm1 + movdqu [edx], xmm0 + movdqu [edx + 16], xmm1 lea edx, [edx + 32] + sub ecx, 8 jg wloop ret @@ -1283,7 +1321,7 @@ void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, } // Divide num by div and return as 16.16 fixed point result. -__declspec(naked) __declspec(align(16)) +__declspec(naked) int FixedDiv_X86(int num, int div) { __asm { mov eax, [esp + 4] // num @@ -1296,7 +1334,7 @@ int FixedDiv_X86(int num, int div) { } // Divide num by div and return as 16.16 fixed point result. -__declspec(naked) __declspec(align(16)) +__declspec(naked) int FixedDiv1_X86(int num, int div) { __asm { mov eax, [esp + 4] // num @@ -1311,8 +1349,7 @@ int FixedDiv1_X86(int num, int div) { ret } } - -#endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) +#endif // !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) #ifdef __cplusplus } // extern "C" diff --git a/TMessagesProj/jni/libyuv/source/video_common.cc b/TMessagesProj/jni/libyuv/source/video_common.cc index efbedf46..379a0669 100644 --- a/TMessagesProj/jni/libyuv/source/video_common.cc +++ b/TMessagesProj/jni/libyuv/source/video_common.cc @@ -33,7 +33,7 @@ static const struct FourCCAliasEntry kFourCCAliases[] = { {FOURCC_2VUY, FOURCC_UYVY}, // kCMPixelFormat_422YpCbCr8 {FOURCC_JPEG, FOURCC_MJPG}, // Note: JPEG has DHT while MJPG does not. {FOURCC_DMB1, FOURCC_MJPG}, - {FOURCC_BA81, FOURCC_BGGR}, + {FOURCC_BA81, FOURCC_BGGR}, // deprecated. {FOURCC_RGB3, FOURCC_RAW }, {FOURCC_BGR3, FOURCC_24BG}, {FOURCC_CM32, FOURCC_BGRA}, // kCMPixelFormat_32ARGB diff --git a/TMessagesProj/jni/libyuv/source/x86inc.asm b/TMessagesProj/jni/libyuv/source/x86inc.asm deleted file mode 100644 index cb5c32df..00000000 --- a/TMessagesProj/jni/libyuv/source/x86inc.asm +++ /dev/null @@ -1,1136 +0,0 @@ -;***************************************************************************** -;* x86inc.asm: x264asm abstraction layer -;***************************************************************************** -;* Copyright (C) 2005-2012 x264 project -;* -;* Authors: Loren Merritt -;* Anton Mitrofanov -;* Jason Garrett-Glaser -;* Henrik Gramner -;* -;* Permission to use, copy, modify, and/or distribute this software for any -;* purpose with or without fee is hereby granted, provided that the above -;* copyright notice and this permission notice appear in all copies. -;* -;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -;***************************************************************************** - -; This is a header file for the x264ASM assembly language, which uses -; NASM/YASM syntax combined with a large number of macros to provide easy -; abstraction between different calling conventions (x86_32, win64, linux64). -; It also has various other useful features to simplify writing the kind of -; DSP functions that are most often used in x264. - -; Unlike the rest of x264, this file is available under an ISC license, as it -; has significant usefulness outside of x264 and we want it to be available -; to the largest audience possible. Of course, if you modify it for your own -; purposes to add a new feature, we strongly encourage contributing a patch -; as this feature might be useful for others as well. Send patches or ideas -; to x264-devel@videolan.org . - -; Local changes for libyuv: -; remove %define program_name and references in labels -; rename cpus to uppercase - -%define WIN64 0 -%define UNIX64 0 -%if ARCH_X86_64 - %ifidn __OUTPUT_FORMAT__,win32 - %define WIN64 1 - %elifidn __OUTPUT_FORMAT__,win64 - %define WIN64 1 - %else - %define UNIX64 1 - %endif -%endif - -%ifdef PREFIX - %define mangle(x) _ %+ x -%else - %define mangle(x) x -%endif - -; Name of the .rodata section. -; Kludge: Something on OS X fails to align .rodata even given an align attribute, -; so use a different read-only section. -%macro SECTION_RODATA 0-1 16 - %ifidn __OUTPUT_FORMAT__,macho64 - SECTION .text align=%1 - %elifidn __OUTPUT_FORMAT__,macho - SECTION .text align=%1 - fakegot: - %elifidn __OUTPUT_FORMAT__,aout - section .text - %else - SECTION .rodata align=%1 - %endif -%endmacro - -; aout does not support align= -%macro SECTION_TEXT 0-1 16 - %ifidn __OUTPUT_FORMAT__,aout - SECTION .text - %else - SECTION .text align=%1 - %endif -%endmacro - -%if WIN64 - %define PIC -%elif ARCH_X86_64 == 0 -; x86_32 doesn't require PIC. -; Some distros prefer shared objects to be PIC, but nothing breaks if -; the code contains a few textrels, so we'll skip that complexity. - %undef PIC -%endif -%ifdef PIC - default rel -%endif - -; Always use long nops (reduces 0x90 spam in disassembly on x86_32) -CPU amdnop - -; Macros to eliminate most code duplication between x86_32 and x86_64: -; Currently this works only for leaf functions which load all their arguments -; into registers at the start, and make no other use of the stack. Luckily that -; covers most of x264's asm. - -; PROLOGUE: -; %1 = number of arguments. loads them from stack if needed. -; %2 = number of registers used. pushes callee-saved regs if needed. -; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed. -; %4 = list of names to define to registers -; PROLOGUE can also be invoked by adding the same options to cglobal - -; e.g. -; cglobal foo, 2,3,0, dst, src, tmp -; declares a function (foo), taking two args (dst and src) and one local variable (tmp) - -; TODO Some functions can use some args directly from the stack. If they're the -; last args then you can just not declare them, but if they're in the middle -; we need more flexible macro. - -; RET: -; Pops anything that was pushed by PROLOGUE, and returns. - -; REP_RET: -; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons -; which are slow when a normal ret follows a branch. - -; registers: -; rN and rNq are the native-size register holding function argument N -; rNd, rNw, rNb are dword, word, and byte size -; rNh is the high 8 bits of the word size -; rNm is the original location of arg N (a register or on the stack), dword -; rNmp is native size - -%macro DECLARE_REG 2-3 - %define r%1q %2 - %define r%1d %2d - %define r%1w %2w - %define r%1b %2b - %define r%1h %2h - %if %0 == 2 - %define r%1m %2d - %define r%1mp %2 - %elif ARCH_X86_64 ; memory - %define r%1m [rsp + stack_offset + %3] - %define r%1mp qword r %+ %1m - %else - %define r%1m [esp + stack_offset + %3] - %define r%1mp dword r %+ %1m - %endif - %define r%1 %2 -%endmacro - -%macro DECLARE_REG_SIZE 3 - %define r%1q r%1 - %define e%1q r%1 - %define r%1d e%1 - %define e%1d e%1 - %define r%1w %1 - %define e%1w %1 - %define r%1h %3 - %define e%1h %3 - %define r%1b %2 - %define e%1b %2 -%if ARCH_X86_64 == 0 - %define r%1 e%1 -%endif -%endmacro - -DECLARE_REG_SIZE ax, al, ah -DECLARE_REG_SIZE bx, bl, bh -DECLARE_REG_SIZE cx, cl, ch -DECLARE_REG_SIZE dx, dl, dh -DECLARE_REG_SIZE si, sil, null -DECLARE_REG_SIZE di, dil, null -DECLARE_REG_SIZE bp, bpl, null - -; t# defines for when per-arch register allocation is more complex than just function arguments - -%macro DECLARE_REG_TMP 1-* - %assign %%i 0 - %rep %0 - CAT_XDEFINE t, %%i, r%1 - %assign %%i %%i+1 - %rotate 1 - %endrep -%endmacro - -%macro DECLARE_REG_TMP_SIZE 0-* - %rep %0 - %define t%1q t%1 %+ q - %define t%1d t%1 %+ d - %define t%1w t%1 %+ w - %define t%1h t%1 %+ h - %define t%1b t%1 %+ b - %rotate 1 - %endrep -%endmacro - -DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 - -%if ARCH_X86_64 - %define gprsize 8 -%else - %define gprsize 4 -%endif - -%macro PUSH 1 - push %1 - %assign stack_offset stack_offset+gprsize -%endmacro - -%macro POP 1 - pop %1 - %assign stack_offset stack_offset-gprsize -%endmacro - -%macro PUSH_IF_USED 1-* - %rep %0 - %if %1 < regs_used - PUSH r%1 - %endif - %rotate 1 - %endrep -%endmacro - -%macro POP_IF_USED 1-* - %rep %0 - %if %1 < regs_used - pop r%1 - %endif - %rotate 1 - %endrep -%endmacro - -%macro LOAD_IF_USED 1-* - %rep %0 - %if %1 < num_args - mov r%1, r %+ %1 %+ mp - %endif - %rotate 1 - %endrep -%endmacro - -%macro SUB 2 - sub %1, %2 - %ifidn %1, rsp - %assign stack_offset stack_offset+(%2) - %endif -%endmacro - -%macro ADD 2 - add %1, %2 - %ifidn %1, rsp - %assign stack_offset stack_offset-(%2) - %endif -%endmacro - -%macro movifnidn 2 - %ifnidn %1, %2 - mov %1, %2 - %endif -%endmacro - -%macro movsxdifnidn 2 - %ifnidn %1, %2 - movsxd %1, %2 - %endif -%endmacro - -%macro ASSERT 1 - %if (%1) == 0 - %error assert failed - %endif -%endmacro - -%macro DEFINE_ARGS 0-* - %ifdef n_arg_names - %assign %%i 0 - %rep n_arg_names - CAT_UNDEF arg_name %+ %%i, q - CAT_UNDEF arg_name %+ %%i, d - CAT_UNDEF arg_name %+ %%i, w - CAT_UNDEF arg_name %+ %%i, h - CAT_UNDEF arg_name %+ %%i, b - CAT_UNDEF arg_name %+ %%i, m - CAT_UNDEF arg_name %+ %%i, mp - CAT_UNDEF arg_name, %%i - %assign %%i %%i+1 - %endrep - %endif - - %xdefine %%stack_offset stack_offset - %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine - %assign %%i 0 - %rep %0 - %xdefine %1q r %+ %%i %+ q - %xdefine %1d r %+ %%i %+ d - %xdefine %1w r %+ %%i %+ w - %xdefine %1h r %+ %%i %+ h - %xdefine %1b r %+ %%i %+ b - %xdefine %1m r %+ %%i %+ m - %xdefine %1mp r %+ %%i %+ mp - CAT_XDEFINE arg_name, %%i, %1 - %assign %%i %%i+1 - %rotate 1 - %endrep - %xdefine stack_offset %%stack_offset - %assign n_arg_names %0 -%endmacro - -%if WIN64 ; Windows x64 ;================================================= - -DECLARE_REG 0, rcx -DECLARE_REG 1, rdx -DECLARE_REG 2, R8 -DECLARE_REG 3, R9 -DECLARE_REG 4, R10, 40 -DECLARE_REG 5, R11, 48 -DECLARE_REG 6, rax, 56 -DECLARE_REG 7, rdi, 64 -DECLARE_REG 8, rsi, 72 -DECLARE_REG 9, rbx, 80 -DECLARE_REG 10, rbp, 88 -DECLARE_REG 11, R12, 96 -DECLARE_REG 12, R13, 104 -DECLARE_REG 13, R14, 112 -DECLARE_REG 14, R15, 120 - -%macro PROLOGUE 2-4+ 0 ; #args, #regs, #xmm_regs, arg_names... - %assign num_args %1 - %assign regs_used %2 - ASSERT regs_used >= num_args - ASSERT regs_used <= 15 - PUSH_IF_USED 7, 8, 9, 10, 11, 12, 13, 14 - %if mmsize == 8 - %assign xmm_regs_used 0 - %else - WIN64_SPILL_XMM %3 - %endif - LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - DEFINE_ARGS %4 -%endmacro - -%macro WIN64_SPILL_XMM 1 - %assign xmm_regs_used %1 - ASSERT xmm_regs_used <= 16 - %if xmm_regs_used > 6 - SUB rsp, (xmm_regs_used-6)*16+16 - %assign %%i xmm_regs_used - %rep (xmm_regs_used-6) - %assign %%i %%i-1 - movdqa [rsp + (%%i-6)*16+(~stack_offset&8)], xmm %+ %%i - %endrep - %endif -%endmacro - -%macro WIN64_RESTORE_XMM_INTERNAL 1 - %if xmm_regs_used > 6 - %assign %%i xmm_regs_used - %rep (xmm_regs_used-6) - %assign %%i %%i-1 - movdqa xmm %+ %%i, [%1 + (%%i-6)*16+(~stack_offset&8)] - %endrep - add %1, (xmm_regs_used-6)*16+16 - %endif -%endmacro - -%macro WIN64_RESTORE_XMM 1 - WIN64_RESTORE_XMM_INTERNAL %1 - %assign stack_offset stack_offset-(xmm_regs_used-6)*16+16 - %assign xmm_regs_used 0 -%endmacro - -%define has_epilogue regs_used > 7 || xmm_regs_used > 6 || mmsize == 32 - -%macro RET 0 - WIN64_RESTORE_XMM_INTERNAL rsp - POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7 -%if mmsize == 32 - vzeroupper -%endif - ret -%endmacro - -%elif ARCH_X86_64 ; *nix x64 ;============================================= - -DECLARE_REG 0, rdi -DECLARE_REG 1, rsi -DECLARE_REG 2, rdx -DECLARE_REG 3, rcx -DECLARE_REG 4, R8 -DECLARE_REG 5, R9 -DECLARE_REG 6, rax, 8 -DECLARE_REG 7, R10, 16 -DECLARE_REG 8, R11, 24 -DECLARE_REG 9, rbx, 32 -DECLARE_REG 10, rbp, 40 -DECLARE_REG 11, R12, 48 -DECLARE_REG 12, R13, 56 -DECLARE_REG 13, R14, 64 -DECLARE_REG 14, R15, 72 - -%macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names... - %assign num_args %1 - %assign regs_used %2 - ASSERT regs_used >= num_args - ASSERT regs_used <= 15 - PUSH_IF_USED 9, 10, 11, 12, 13, 14 - LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14 - DEFINE_ARGS %4 -%endmacro - -%define has_epilogue regs_used > 9 || mmsize == 32 - -%macro RET 0 - POP_IF_USED 14, 13, 12, 11, 10, 9 -%if mmsize == 32 - vzeroupper -%endif - ret -%endmacro - -%else ; X86_32 ;============================================================== - -DECLARE_REG 0, eax, 4 -DECLARE_REG 1, ecx, 8 -DECLARE_REG 2, edx, 12 -DECLARE_REG 3, ebx, 16 -DECLARE_REG 4, esi, 20 -DECLARE_REG 5, edi, 24 -DECLARE_REG 6, ebp, 28 -%define rsp esp - -%macro DECLARE_ARG 1-* - %rep %0 - %define r%1m [esp + stack_offset + 4*%1 + 4] - %define r%1mp dword r%1m - %rotate 1 - %endrep -%endmacro - -DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 - -%macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names... - %assign num_args %1 - %assign regs_used %2 - %if regs_used > 7 - %assign regs_used 7 - %endif - ASSERT regs_used >= num_args - PUSH_IF_USED 3, 4, 5, 6 - LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6 - DEFINE_ARGS %4 -%endmacro - -%define has_epilogue regs_used > 3 || mmsize == 32 - -%macro RET 0 - POP_IF_USED 6, 5, 4, 3 -%if mmsize == 32 - vzeroupper -%endif - ret -%endmacro - -%endif ;====================================================================== - -%if WIN64 == 0 -%macro WIN64_SPILL_XMM 1 -%endmacro -%macro WIN64_RESTORE_XMM 1 -%endmacro -%endif - -%macro REP_RET 0 - %if has_epilogue - RET - %else - rep ret - %endif -%endmacro - -%macro TAIL_CALL 2 ; callee, is_nonadjacent - %if has_epilogue - call %1 - RET - %elif %2 - jmp %1 - %endif -%endmacro - -;============================================================================= -; arch-independent part -;============================================================================= - -%assign function_align 16 - -; Begin a function. -; Applies any symbol mangling needed for C linkage, and sets up a define such that -; subsequent uses of the function name automatically refer to the mangled version. -; Appends cpuflags to the function name if cpuflags has been specified. -%macro cglobal 1-2+ ; name, [PROLOGUE args] -%if %0 == 1 - cglobal_internal %1 %+ SUFFIX -%else - cglobal_internal %1 %+ SUFFIX, %2 -%endif -%endmacro -%macro cglobal_internal 1-2+ - %ifndef cglobaled_%1 - %xdefine %1 mangle(%1) - %xdefine %1.skip_prologue %1 %+ .skip_prologue - CAT_XDEFINE cglobaled_, %1, 1 - %endif - %xdefine current_function %1 - %ifidn __OUTPUT_FORMAT__,elf - global %1:function hidden - %else - global %1 - %endif - align function_align - %1: - RESET_MM_PERMUTATION ; not really needed, but makes disassembly somewhat nicer - %assign stack_offset 0 - %if %0 > 1 - PROLOGUE %2 - %endif -%endmacro - -%macro cextern 1 - %xdefine %1 mangle(%1) - CAT_XDEFINE cglobaled_, %1, 1 - extern %1 -%endmacro - -; like cextern, but without the prefix -%macro cextern_naked 1 - %xdefine %1 mangle(%1) - CAT_XDEFINE cglobaled_, %1, 1 - extern %1 -%endmacro - -%macro const 2+ - %xdefine %1 mangle(%1) - global %1 - %1: %2 -%endmacro - -; This is needed for ELF, otherwise the GNU linker assumes the stack is -; executable by default. -%ifidn __OUTPUT_FORMAT__,elf -SECTION .note.GNU-stack noalloc noexec nowrite progbits -%endif -%ifidn __OUTPUT_FORMAT__,elf32 -section .note.GNU-stack noalloc noexec nowrite progbits -%endif -%ifidn __OUTPUT_FORMAT__,elf64 -section .note.GNU-stack noalloc noexec nowrite progbits -%endif - -; cpuflags - -%assign cpuflags_MMX (1<<0) -%assign cpuflags_MMX2 (1<<1) | cpuflags_MMX -%assign cpuflags_3dnow (1<<2) | cpuflags_MMX -%assign cpuflags_3dnow2 (1<<3) | cpuflags_3dnow -%assign cpuflags_SSE (1<<4) | cpuflags_MMX2 -%assign cpuflags_SSE2 (1<<5) | cpuflags_SSE -%assign cpuflags_SSE2slow (1<<6) | cpuflags_SSE2 -%assign cpuflags_SSE3 (1<<7) | cpuflags_SSE2 -%assign cpuflags_SSSE3 (1<<8) | cpuflags_SSE3 -%assign cpuflags_SSE4 (1<<9) | cpuflags_SSSE3 -%assign cpuflags_SSE42 (1<<10)| cpuflags_SSE4 -%assign cpuflags_AVX (1<<11)| cpuflags_SSE42 -%assign cpuflags_xop (1<<12)| cpuflags_AVX -%assign cpuflags_fma4 (1<<13)| cpuflags_AVX -%assign cpuflags_AVX2 (1<<14)| cpuflags_AVX -%assign cpuflags_fma3 (1<<15)| cpuflags_AVX - -%assign cpuflags_cache32 (1<<16) -%assign cpuflags_cache64 (1<<17) -%assign cpuflags_slowctz (1<<18) -%assign cpuflags_lzcnt (1<<19) -%assign cpuflags_misalign (1<<20) -%assign cpuflags_aligned (1<<21) ; not a cpu feature, but a function variant -%assign cpuflags_atom (1<<22) -%assign cpuflags_bmi1 (1<<23) -%assign cpuflags_bmi2 (1<<24)|cpuflags_bmi1 -%assign cpuflags_tbm (1<<25)|cpuflags_bmi1 - -%define cpuflag(x) ((cpuflags & (cpuflags_ %+ x)) == (cpuflags_ %+ x)) -%define notcpuflag(x) ((cpuflags & (cpuflags_ %+ x)) != (cpuflags_ %+ x)) - -; Takes up to 2 cpuflags from the above list. -; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu. -; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co. -%macro INIT_CPUFLAGS 0-2 - %if %0 >= 1 - %xdefine cpuname %1 - %assign cpuflags cpuflags_%1 - %if %0 >= 2 - %xdefine cpuname %1_%2 - %assign cpuflags cpuflags | cpuflags_%2 - %endif - %xdefine SUFFIX _ %+ cpuname - %if cpuflag(AVX) - %assign AVX_enabled 1 - %endif - %if mmsize == 16 && notcpuflag(SSE2) - %define mova movaps - %define movu movups - %define movnta movntps - %endif - %if cpuflag(aligned) - %define movu mova - %elifidn %1, SSE3 - %define movu lddqu - %endif - %else - %xdefine SUFFIX - %undef cpuname - %undef cpuflags - %endif -%endmacro - -; merge MMX and SSE* - -%macro CAT_XDEFINE 3 - %xdefine %1%2 %3 -%endmacro - -%macro CAT_UNDEF 2 - %undef %1%2 -%endmacro - -%macro INIT_MMX 0-1+ - %assign AVX_enabled 0 - %define RESET_MM_PERMUTATION INIT_MMX %1 - %define mmsize 8 - %define num_mmregs 8 - %define mova movq - %define movu movq - %define movh movd - %define movnta movntq - %assign %%i 0 - %rep 8 - CAT_XDEFINE m, %%i, mm %+ %%i - CAT_XDEFINE nmm, %%i, %%i - %assign %%i %%i+1 - %endrep - %rep 8 - CAT_UNDEF m, %%i - CAT_UNDEF nmm, %%i - %assign %%i %%i+1 - %endrep - INIT_CPUFLAGS %1 -%endmacro - -%macro INIT_XMM 0-1+ - %assign AVX_enabled 0 - %define RESET_MM_PERMUTATION INIT_XMM %1 - %define mmsize 16 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 16 - %endif - %define mova movdqa - %define movu movdqu - %define movh movq - %define movnta movntdq - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, xmm %+ %%i - CAT_XDEFINE nxmm, %%i, %%i - %assign %%i %%i+1 - %endrep - INIT_CPUFLAGS %1 -%endmacro - -%macro INIT_YMM 0-1+ - %assign AVX_enabled 1 - %define RESET_MM_PERMUTATION INIT_YMM %1 - %define mmsize 32 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 16 - %endif - %define mova vmovaps - %define movu vmovups - %undef movh - %define movnta vmovntps - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, ymm %+ %%i - CAT_XDEFINE nymm, %%i, %%i - %assign %%i %%i+1 - %endrep - INIT_CPUFLAGS %1 -%endmacro - -INIT_XMM - -; I often want to use macros that permute their arguments. e.g. there's no -; efficient way to implement butterfly or transpose or dct without swapping some -; arguments. -; -; I would like to not have to manually keep track of the permutations: -; If I insert a permutation in the middle of a function, it should automatically -; change everything that follows. For more complex macros I may also have multiple -; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations. -; -; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that -; permutes its arguments. It's equivalent to exchanging the contents of the -; registers, except that this way you exchange the register names instead, so it -; doesn't cost any cycles. - -%macro PERMUTE 2-* ; takes a list of pairs to swap -%rep %0/2 - %xdefine tmp%2 m%2 - %xdefine ntmp%2 nm%2 - %rotate 2 -%endrep -%rep %0/2 - %xdefine m%1 tmp%2 - %xdefine nm%1 ntmp%2 - %undef tmp%2 - %undef ntmp%2 - %rotate 2 -%endrep -%endmacro - -%macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs) -%rep %0-1 -%ifdef m%1 - %xdefine tmp m%1 - %xdefine m%1 m%2 - %xdefine m%2 tmp - CAT_XDEFINE n, m%1, %1 - CAT_XDEFINE n, m%2, %2 -%else - ; If we were called as "SWAP m0,m1" rather than "SWAP 0,1" infer the original numbers here. - ; Be careful using this mode in nested macros though, as in some cases there may be - ; other copies of m# that have already been dereferenced and don't get updated correctly. - %xdefine %%n1 n %+ %1 - %xdefine %%n2 n %+ %2 - %xdefine tmp m %+ %%n1 - CAT_XDEFINE m, %%n1, m %+ %%n2 - CAT_XDEFINE m, %%n2, tmp - CAT_XDEFINE n, m %+ %%n1, %%n1 - CAT_XDEFINE n, m %+ %%n2, %%n2 -%endif - %undef tmp - %rotate 1 -%endrep -%endmacro - -; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later -; calls to that function will automatically load the permutation, so values can -; be returned in mmregs. -%macro SAVE_MM_PERMUTATION 0-1 - %if %0 - %xdefine %%f %1_m - %else - %xdefine %%f current_function %+ _m - %endif - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE %%f, %%i, m %+ %%i - %assign %%i %%i+1 - %endrep -%endmacro - -%macro LOAD_MM_PERMUTATION 1 ; name to load from - %ifdef %1_m0 - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, %1_m %+ %%i - CAT_XDEFINE n, m %+ %%i, %%i - %assign %%i %%i+1 - %endrep - %endif -%endmacro - -; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't -%macro call 1 - call_internal %1, %1 %+ SUFFIX -%endmacro -%macro call_internal 2 - %xdefine %%i %1 - %ifndef cglobaled_%1 - %ifdef cglobaled_%2 - %xdefine %%i %2 - %endif - %endif - call %%i - LOAD_MM_PERMUTATION %%i -%endmacro - -; Substitutions that reduce instruction size but are functionally equivalent -%macro add 2 - %ifnum %2 - %if %2==128 - sub %1, -128 - %else - add %1, %2 - %endif - %else - add %1, %2 - %endif -%endmacro - -%macro sub 2 - %ifnum %2 - %if %2==128 - add %1, -128 - %else - sub %1, %2 - %endif - %else - sub %1, %2 - %endif -%endmacro - -;============================================================================= -; AVX abstraction layer -;============================================================================= - -%assign i 0 -%rep 16 - %if i < 8 - CAT_XDEFINE sizeofmm, i, 8 - %endif - CAT_XDEFINE sizeofxmm, i, 16 - CAT_XDEFINE sizeofymm, i, 32 -%assign i i+1 -%endrep -%undef i - -%macro CHECK_AVX_INSTR_EMU 3-* - %xdefine %%opcode %1 - %xdefine %%dst %2 - %rep %0-2 - %ifidn %%dst, %3 - %error non-AVX emulation of ``%%opcode'' is not supported - %endif - %rotate 1 - %endrep -%endmacro - -;%1 == instruction -;%2 == 1 if float, 0 if int -;%3 == 1 if 4-operand (xmm, xmm, xmm, imm), 0 if 2- or 3-operand (xmm, xmm, xmm) -;%4 == number of operands given -;%5+: operands -%macro RUN_AVX_INSTR 6-7+ - %ifid %6 - %define %%sizeofreg sizeof%6 - %elifid %5 - %define %%sizeofreg sizeof%5 - %else - %define %%sizeofreg mmsize - %endif - %if %%sizeofreg==32 - %if %4>=3 - v%1 %5, %6, %7 - %else - v%1 %5, %6 - %endif - %else - %if %%sizeofreg==8 - %define %%regmov movq - %elif %2 - %define %%regmov movaps - %else - %define %%regmov movdqa - %endif - - %if %4>=3+%3 - %ifnidn %5, %6 - %if AVX_enabled && %%sizeofreg==16 - v%1 %5, %6, %7 - %else - CHECK_AVX_INSTR_EMU {%1 %5, %6, %7}, %5, %7 - %%regmov %5, %6 - %1 %5, %7 - %endif - %else - %1 %5, %7 - %endif - %elif %4>=3 - %1 %5, %6, %7 - %else - %1 %5, %6 - %endif - %endif -%endmacro - -; 3arg AVX ops with a memory arg can only have it in src2, -; whereas SSE emulation of 3arg prefers to have it in src1 (i.e. the mov). -; So, if the op is symmetric and the wrong one is memory, swap them. -%macro RUN_AVX_INSTR1 8 - %assign %%swap 0 - %if AVX_enabled - %ifnid %6 - %assign %%swap 1 - %endif - %elifnidn %5, %6 - %ifnid %7 - %assign %%swap 1 - %endif - %endif - %if %%swap && %3 == 0 && %8 == 1 - RUN_AVX_INSTR %1, %2, %3, %4, %5, %7, %6 - %else - RUN_AVX_INSTR %1, %2, %3, %4, %5, %6, %7 - %endif -%endmacro - -;%1 == instruction -;%2 == 1 if float, 0 if int -;%3 == 1 if 4-operand (xmm, xmm, xmm, imm), 0 if 2- or 3-operand (xmm, xmm, xmm) -;%4 == 1 if symmetric (i.e. doesn't matter which src arg is which), 0 if not -%macro AVX_INSTR 4 - %macro %1 2-9 fnord, fnord, fnord, %1, %2, %3, %4 - %ifidn %3, fnord - RUN_AVX_INSTR %6, %7, %8, 2, %1, %2 - %elifidn %4, fnord - RUN_AVX_INSTR1 %6, %7, %8, 3, %1, %2, %3, %9 - %elifidn %5, fnord - RUN_AVX_INSTR %6, %7, %8, 4, %1, %2, %3, %4 - %else - RUN_AVX_INSTR %6, %7, %8, 5, %1, %2, %3, %4, %5 - %endif - %endmacro -%endmacro - -AVX_INSTR addpd, 1, 0, 1 -AVX_INSTR addps, 1, 0, 1 -AVX_INSTR addsd, 1, 0, 1 -AVX_INSTR addss, 1, 0, 1 -AVX_INSTR addsubpd, 1, 0, 0 -AVX_INSTR addsubps, 1, 0, 0 -AVX_INSTR andpd, 1, 0, 1 -AVX_INSTR andps, 1, 0, 1 -AVX_INSTR andnpd, 1, 0, 0 -AVX_INSTR andnps, 1, 0, 0 -AVX_INSTR blendpd, 1, 0, 0 -AVX_INSTR blendps, 1, 0, 0 -AVX_INSTR blendvpd, 1, 0, 0 -AVX_INSTR blendvps, 1, 0, 0 -AVX_INSTR cmppd, 1, 0, 0 -AVX_INSTR cmpps, 1, 0, 0 -AVX_INSTR cmpsd, 1, 0, 0 -AVX_INSTR cmpss, 1, 0, 0 -AVX_INSTR cvtdq2ps, 1, 0, 0 -AVX_INSTR cvtps2dq, 1, 0, 0 -AVX_INSTR divpd, 1, 0, 0 -AVX_INSTR divps, 1, 0, 0 -AVX_INSTR divsd, 1, 0, 0 -AVX_INSTR divss, 1, 0, 0 -AVX_INSTR dppd, 1, 1, 0 -AVX_INSTR dpps, 1, 1, 0 -AVX_INSTR haddpd, 1, 0, 0 -AVX_INSTR haddps, 1, 0, 0 -AVX_INSTR hsubpd, 1, 0, 0 -AVX_INSTR hsubps, 1, 0, 0 -AVX_INSTR maxpd, 1, 0, 1 -AVX_INSTR maxps, 1, 0, 1 -AVX_INSTR maxsd, 1, 0, 1 -AVX_INSTR maxss, 1, 0, 1 -AVX_INSTR minpd, 1, 0, 1 -AVX_INSTR minps, 1, 0, 1 -AVX_INSTR minsd, 1, 0, 1 -AVX_INSTR minss, 1, 0, 1 -AVX_INSTR movhlps, 1, 0, 0 -AVX_INSTR movlhps, 1, 0, 0 -AVX_INSTR movsd, 1, 0, 0 -AVX_INSTR movss, 1, 0, 0 -AVX_INSTR mpsadbw, 0, 1, 0 -AVX_INSTR mulpd, 1, 0, 1 -AVX_INSTR mulps, 1, 0, 1 -AVX_INSTR mulsd, 1, 0, 1 -AVX_INSTR mulss, 1, 0, 1 -AVX_INSTR orpd, 1, 0, 1 -AVX_INSTR orps, 1, 0, 1 -AVX_INSTR pabsb, 0, 0, 0 -AVX_INSTR pabsw, 0, 0, 0 -AVX_INSTR pabsd, 0, 0, 0 -AVX_INSTR packsswb, 0, 0, 0 -AVX_INSTR packssdw, 0, 0, 0 -AVX_INSTR packuswb, 0, 0, 0 -AVX_INSTR packusdw, 0, 0, 0 -AVX_INSTR paddb, 0, 0, 1 -AVX_INSTR paddw, 0, 0, 1 -AVX_INSTR paddd, 0, 0, 1 -AVX_INSTR paddq, 0, 0, 1 -AVX_INSTR paddsb, 0, 0, 1 -AVX_INSTR paddsw, 0, 0, 1 -AVX_INSTR paddusb, 0, 0, 1 -AVX_INSTR paddusw, 0, 0, 1 -AVX_INSTR palignr, 0, 1, 0 -AVX_INSTR pand, 0, 0, 1 -AVX_INSTR pandn, 0, 0, 0 -AVX_INSTR pavgb, 0, 0, 1 -AVX_INSTR pavgw, 0, 0, 1 -AVX_INSTR pblendvb, 0, 0, 0 -AVX_INSTR pblendw, 0, 1, 0 -AVX_INSTR pcmpestri, 0, 0, 0 -AVX_INSTR pcmpestrm, 0, 0, 0 -AVX_INSTR pcmpistri, 0, 0, 0 -AVX_INSTR pcmpistrm, 0, 0, 0 -AVX_INSTR pcmpeqb, 0, 0, 1 -AVX_INSTR pcmpeqw, 0, 0, 1 -AVX_INSTR pcmpeqd, 0, 0, 1 -AVX_INSTR pcmpeqq, 0, 0, 1 -AVX_INSTR pcmpgtb, 0, 0, 0 -AVX_INSTR pcmpgtw, 0, 0, 0 -AVX_INSTR pcmpgtd, 0, 0, 0 -AVX_INSTR pcmpgtq, 0, 0, 0 -AVX_INSTR phaddw, 0, 0, 0 -AVX_INSTR phaddd, 0, 0, 0 -AVX_INSTR phaddsw, 0, 0, 0 -AVX_INSTR phsubw, 0, 0, 0 -AVX_INSTR phsubd, 0, 0, 0 -AVX_INSTR phsubsw, 0, 0, 0 -AVX_INSTR pmaddwd, 0, 0, 1 -AVX_INSTR pmaddubsw, 0, 0, 0 -AVX_INSTR pmaxsb, 0, 0, 1 -AVX_INSTR pmaxsw, 0, 0, 1 -AVX_INSTR pmaxsd, 0, 0, 1 -AVX_INSTR pmaxub, 0, 0, 1 -AVX_INSTR pmaxuw, 0, 0, 1 -AVX_INSTR pmaxud, 0, 0, 1 -AVX_INSTR pminsb, 0, 0, 1 -AVX_INSTR pminsw, 0, 0, 1 -AVX_INSTR pminsd, 0, 0, 1 -AVX_INSTR pminub, 0, 0, 1 -AVX_INSTR pminuw, 0, 0, 1 -AVX_INSTR pminud, 0, 0, 1 -AVX_INSTR pmovmskb, 0, 0, 0 -AVX_INSTR pmulhuw, 0, 0, 1 -AVX_INSTR pmulhrsw, 0, 0, 1 -AVX_INSTR pmulhw, 0, 0, 1 -AVX_INSTR pmullw, 0, 0, 1 -AVX_INSTR pmulld, 0, 0, 1 -AVX_INSTR pmuludq, 0, 0, 1 -AVX_INSTR pmuldq, 0, 0, 1 -AVX_INSTR por, 0, 0, 1 -AVX_INSTR psadbw, 0, 0, 1 -AVX_INSTR pshufb, 0, 0, 0 -AVX_INSTR pshufd, 0, 1, 0 -AVX_INSTR pshufhw, 0, 1, 0 -AVX_INSTR pshuflw, 0, 1, 0 -AVX_INSTR psignb, 0, 0, 0 -AVX_INSTR psignw, 0, 0, 0 -AVX_INSTR psignd, 0, 0, 0 -AVX_INSTR psllw, 0, 0, 0 -AVX_INSTR pslld, 0, 0, 0 -AVX_INSTR psllq, 0, 0, 0 -AVX_INSTR pslldq, 0, 0, 0 -AVX_INSTR psraw, 0, 0, 0 -AVX_INSTR psrad, 0, 0, 0 -AVX_INSTR psrlw, 0, 0, 0 -AVX_INSTR psrld, 0, 0, 0 -AVX_INSTR psrlq, 0, 0, 0 -AVX_INSTR psrldq, 0, 0, 0 -AVX_INSTR psubb, 0, 0, 0 -AVX_INSTR psubw, 0, 0, 0 -AVX_INSTR psubd, 0, 0, 0 -AVX_INSTR psubq, 0, 0, 0 -AVX_INSTR psubsb, 0, 0, 0 -AVX_INSTR psubsw, 0, 0, 0 -AVX_INSTR psubusb, 0, 0, 0 -AVX_INSTR psubusw, 0, 0, 0 -AVX_INSTR ptest, 0, 0, 0 -AVX_INSTR punpckhbw, 0, 0, 0 -AVX_INSTR punpckhwd, 0, 0, 0 -AVX_INSTR punpckhdq, 0, 0, 0 -AVX_INSTR punpckhqdq, 0, 0, 0 -AVX_INSTR punpcklbw, 0, 0, 0 -AVX_INSTR punpcklwd, 0, 0, 0 -AVX_INSTR punpckldq, 0, 0, 0 -AVX_INSTR punpcklqdq, 0, 0, 0 -AVX_INSTR pxor, 0, 0, 1 -AVX_INSTR shufps, 1, 1, 0 -AVX_INSTR subpd, 1, 0, 0 -AVX_INSTR subps, 1, 0, 0 -AVX_INSTR subsd, 1, 0, 0 -AVX_INSTR subss, 1, 0, 0 -AVX_INSTR unpckhpd, 1, 0, 0 -AVX_INSTR unpckhps, 1, 0, 0 -AVX_INSTR unpcklpd, 1, 0, 0 -AVX_INSTR unpcklps, 1, 0, 0 -AVX_INSTR xorpd, 1, 0, 1 -AVX_INSTR xorps, 1, 0, 1 - -; 3DNow instructions, for sharing code between AVX, SSE and 3DN -AVX_INSTR pfadd, 1, 0, 1 -AVX_INSTR pfsub, 1, 0, 0 -AVX_INSTR pfmul, 1, 0, 1 - -; base-4 constants for shuffles -%assign i 0 -%rep 256 - %assign j ((i>>6)&3)*1000 + ((i>>4)&3)*100 + ((i>>2)&3)*10 + (i&3) - %if j < 10 - CAT_XDEFINE q000, j, i - %elif j < 100 - CAT_XDEFINE q00, j, i - %elif j < 1000 - CAT_XDEFINE q0, j, i - %else - CAT_XDEFINE q, j, i - %endif -%assign i i+1 -%endrep -%undef i -%undef j - -%macro FMA_INSTR 3 - %macro %1 4-7 %1, %2, %3 - %if cpuflag(xop) - v%5 %1, %2, %3, %4 - %else - %6 %1, %2, %3 - %7 %1, %4 - %endif - %endmacro -%endmacro - -FMA_INSTR pmacsdd, pmulld, paddd -FMA_INSTR pmacsww, pmullw, paddw -FMA_INSTR pmadcswd, pmaddwd, paddd - -; tzcnt is equivalent to "rep bsf" and is backwards-compatible with bsf. -; This lets us use tzcnt without bumping the yasm version requirement yet. -%define tzcnt rep bsf diff --git a/TMessagesProj/jni/sqlite/sqlite3.c b/TMessagesProj/jni/sqlite/sqlite3.c index 73ee2685..486eefee 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.c +++ b/TMessagesProj/jni/sqlite/sqlite3.c @@ -17,6 +17,7 @@ ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. */ +#define SQLITE_THREADSAFE 0 #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE diff --git a/TMessagesProj/jni/utils.h b/TMessagesProj/jni/utils.h index f17ae902..34805a1d 100644 --- a/TMessagesProj/jni/utils.h +++ b/TMessagesProj/jni/utils.h @@ -4,7 +4,7 @@ #include #include -#define LOG_TAG "tmessages" +#define LOG_TAG "tmessages_native" #ifndef LOG_DISABLED #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 957bc7e6..057df939 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -39,13 +39,14 @@ + android:theme="@style/Theme.TMessages.Start" + android:manageSpaceActivity="org.telegram.ui.ManageSpaceActivity"> - + + + - + - + - + - + @@ -148,7 +156,7 @@ android:resource="@xml/auth"/> - + @@ -168,11 +176,12 @@ - - - + + + + - + @@ -191,7 +200,7 @@ - + @@ -199,8 +208,8 @@ - - + diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java index 01275c5a..b667c7fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java index eb8bd6ad..c68c62db 100644 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java index 2540c094..fa068088 100644 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java index 944d2143..2db0736c 100644 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index cd933701..6135e037 100644 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.SQLite; @@ -135,6 +135,10 @@ public class SQLitePreparedStatement { bindLong(sqliteStatementHandle, index, value); } + public void bindNull(int index) throws SQLiteException { + bindNull(sqliteStatementHandle, index); + } + native void bindByteBuffer(int statementHandle, int index, ByteBuffer value, int length) throws SQLiteException; native void bindString(int statementHandle, int index, String value) throws SQLiteException; native void bindInt(int statementHandle, int index, int value) throws SQLiteException; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 9faedd89..d569158f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; @@ -22,7 +22,6 @@ import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.PowerManager; @@ -30,8 +29,8 @@ import android.util.Base64; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; -import com.google.android.gms.gcm.GoogleCloudMessaging; +import org.telegram.SQLite.DatabaseHandler; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; @@ -40,17 +39,11 @@ import org.telegram.ui.Components.ForegroundDetector; import java.io.File; import java.io.RandomAccessFile; import java.util.Calendar; -import java.util.concurrent.atomic.AtomicInteger; public class ApplicationLoader extends Application { + private static NetworkAlarm networkAlarm = null; + private static PendingIntent pendingIntent; - private GoogleCloudMessaging gcm; - private AtomicInteger msgId = new AtomicInteger(); - private String regid; - public static final String EXTRA_MESSAGE = "message"; - public static final String PROPERTY_REG_ID = "registration_id"; - private static final String PROPERTY_APP_VERSION = "appVersion"; - private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; private static Drawable cachedWallpaper; private static int selectedColor; private static boolean isCustomTheme; @@ -63,6 +56,7 @@ public class ApplicationLoader extends Application { public static volatile boolean isScreenOn = false; public static volatile boolean mainInterfacePaused = true; + public static DatabaseHandler databaseHandler; public static boolean SHOW_ANDROID_EMOJI; public static boolean KEEP_ORIGINAL_FILENAME; public static boolean USE_DEVICE_FONT; @@ -186,7 +180,8 @@ public class ApplicationLoader extends Application { } catch (Exception e) { FileLog.e("tmessages", e); } - return new File("/data/data/org.telegram.messenger/files"); + //return new File("/data/data/org.telegram.messenger/files"); + return new File("/data/data/org.telegram." + (BuildConfig.DEBUG ? "plus.beta" : "plus") +"/files"); } public static void postInitApplication() { @@ -239,16 +234,16 @@ public class ApplicationLoader extends Application { appVersion = "App version unknown"; systemVersion = "SDK " + Build.VERSION.SDK_INT; } - if (langCode.length() == 0) { + if (langCode.trim().length() == 0) { langCode = "en"; } - if (deviceModel.length() == 0) { + if (deviceModel.trim().length() == 0) { deviceModel = "Android unknown"; } - if (appVersion.length() == 0) { + if (appVersion.trim().length() == 0) { appVersion = "App version unknown"; } - if (systemVersion.length() == 0) { + if (systemVersion.trim().length() == 0) { systemVersion = "SDK Unknown"; } @@ -280,7 +275,11 @@ public class ApplicationLoader extends Application { applicationContext = getApplicationContext(); NativeLoader.initNativeLibs(ApplicationLoader.applicationContext); - ConnectionsManager.native_setJava(Build.VERSION.SDK_INT == 14 || Build.VERSION.SDK_INT == 15); + try{ + ConnectionsManager.native_setJava(Build.VERSION.SDK_INT == 14 || Build.VERSION.SDK_INT == 15); + } catch (Exception e) { + FileLog.e("tmessages", e); + } if (Build.VERSION.SDK_INT >= 14) { new ForegroundDetector(this); @@ -288,10 +287,12 @@ public class ApplicationLoader extends Application { applicationHandler = new Handler(applicationContext.getMainLooper()); //plus - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SHOW_ANDROID_EMOJI = preferences.getBoolean("showAndroidEmoji", false); - KEEP_ORIGINAL_FILENAME = preferences.getBoolean("keepOriginalFilename", false); - USE_DEVICE_FONT = preferences.getBoolean("useDeviceFont", false); + databaseHandler = new DatabaseHandler(applicationContext); + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + SHOW_ANDROID_EMOJI = plusPreferences.getBoolean("showAndroidEmoji", false); + KEEP_ORIGINAL_FILENAME = plusPreferences.getBoolean("keepOriginalFilename", false); + USE_DEVICE_FONT = plusPreferences.getBoolean("useDeviceFont", false); // startPushService(); } @@ -300,13 +301,22 @@ public class ApplicationLoader extends Application { SharedPreferences preferences = applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE); if (preferences.getBoolean("pushService", true)) { + networkAlarm = new NetworkAlarm(); + /*} else { + AlarmManager am = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE); + Intent i = new Intent(applicationContext, ApplicationLoader.class); + pendingIntent = PendingIntent.getBroadcast(applicationContext, 0, i, 0); + + am.cancel(pendingIntent); + am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pendingIntent); + }*/ applicationContext.startService(new Intent(applicationContext, NotificationsService.class)); //if (android.os.Build.VERSION.SDK_INT >= 19) { - FileLog.e("ApplicationLoader", "startPushService"); - Calendar cal = Calendar.getInstance(); - PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0); - AlarmManager alarm = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE); - alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30000, pintent); + ///FileLog.e("ApplicationLoader", "startPushService"); + ///Calendar cal = Calendar.getInstance(); + ///PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0); + ///AlarmManager alarm = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE); + ///alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30000, pintent); //PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0); //AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE); @@ -318,13 +328,26 @@ public class ApplicationLoader extends Application { } public static void stopPushService() { + if (networkAlarm != null) { + networkAlarm = null; + }// else { + // AlarmManager am = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE); + // am.cancel(pendingIntent); + //} applicationContext.stopService(new Intent(applicationContext, NotificationsService.class)); - PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0); - AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE); - alarm.cancel(pintent); + ///PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, NotificationsService.class), 0); + ///AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE); + ///alarm.cancel(pintent); } + public static void setAlarm(int timeout) { + FileLog.d("tmessages", "setting alarm to wake us in " + String.valueOf(timeout) + "ms"); + + if (networkAlarm != null) { + networkAlarm.setAlarm(applicationContext, timeout); + } + } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -341,13 +364,10 @@ public class ApplicationLoader extends Application { @Override public void run() { if (checkPlayServices()) { - gcm = GoogleCloudMessaging.getInstance(ApplicationLoader.this); - regid = getRegistrationId(); - - if (regid.length() == 0) { - registerInBackground(); - } else { - sendRegistrationIdToBackend(false); + if (UserConfig.pushString == null || UserConfig.pushString.length() == 0) { + FileLog.d("tmessages", "GCM Registration not found."); + Intent intent = new Intent(applicationContext, GcmRegistrationIntentService.class); + startService(intent); } } else { FileLog.d("tmessages", "No valid Google Play Services APK found."); @@ -369,91 +389,4 @@ public class ApplicationLoader extends Application { } return true;*/ } - - private String getRegistrationId() { - final SharedPreferences prefs = getGCMPreferences(applicationContext); - String registrationId = prefs.getString(PROPERTY_REG_ID, ""); - if (registrationId.length() == 0) { - FileLog.d("tmessages", "Registration not found."); - return ""; - } - int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); - if (registeredVersion != BuildVars.BUILD_VERSION) { - FileLog.d("tmessages", "App version changed."); - return ""; - } - return registrationId; - } - - private SharedPreferences getGCMPreferences(Context context) { - return getSharedPreferences(ApplicationLoader.class.getSimpleName(), Context.MODE_PRIVATE); - } - - private void registerInBackground() { - AsyncTask task = new AsyncTask() { - @Override - protected Boolean doInBackground(String... objects) { - if (gcm == null) { - gcm = GoogleCloudMessaging.getInstance(applicationContext); - } - int count = 0; - while (count < 1000) { - try { - count++; - regid = gcm.register(BuildVars.GCM_SENDER_ID); - sendRegistrationIdToBackend(true); - storeRegistrationId(applicationContext, regid); - return true; - } catch (Exception e) { - FileLog.e("tmessages", e); - } - try { - if (count % 20 == 0) { - Thread.sleep(60000 * 30); - } else { - Thread.sleep(5000); - } - } catch (InterruptedException e) { - FileLog.e("tmessages", e); - } - } - return false; - } - }; - - if (android.os.Build.VERSION.SDK_INT >= 11) { - task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null); - } else { - task.execute(null, null, null); - } - } - - private void sendRegistrationIdToBackend(final boolean isNew) { - Utilities.stageQueue.postRunnable(new Runnable() { - @Override - public void run() { - UserConfig.pushString = regid; - UserConfig.registeredForPush = !isNew; - UserConfig.saveConfig(false); - if (UserConfig.getClientUserId() != 0) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - MessagesController.getInstance().registerForPush(regid); - } - }); - } - } - }); - } - - private void storeRegistrationId(Context context, String regId) { - final SharedPreferences prefs = getGCMPreferences(context); - int appVersion = BuildVars.BUILD_VERSION; - FileLog.e("tmessages", "Saving regId on app version " + appVersion); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(PROPERTY_REG_ID, regId); - editor.putInt(PROPERTY_APP_VERSION, appVersion); - editor.commit(); - } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index b28d0a6e..6dce277e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index ec4373bd..4e18382e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; @@ -13,8 +13,8 @@ import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import java.io.RandomAccessFile; import java.io.File; +import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Scanner; @@ -22,9 +22,9 @@ import java.util.Scanner; public class FileLoadOperation { private static class RequestInfo { - private int requestToken = 0; - private int offset = 0; - private TLRPC.TL_upload_file response = null; + private int requestToken; + private int offset; + private TLRPC.TL_upload_file response; } private final static int stateIdle = 0; @@ -49,8 +49,9 @@ public class FileLoadOperation { private int currentDownloadChunkSize; private int currentMaxDownloadRequests; private int requestsCount; + private int renameRetryCount; - private int nextDownloadOffset = 0; + private int nextDownloadOffset; private ArrayList requestInfos; private ArrayList delayedRequestInfos; @@ -61,9 +62,9 @@ public class FileLoadOperation { private String ext; private RandomAccessFile fileOutputStream; private RandomAccessFile fiv; - private File storePath = null; - private File tempPath = null; - private boolean isForceRequest = false; + private File storePath; + private File tempPath; + private boolean isForceRequest; private static String orgName = null; @@ -145,23 +146,28 @@ public class FileLoadOperation { key = documentLocation.key; } else if (documentLocation instanceof TLRPC.TL_document) { location = new TLRPC.TL_inputDocumentFileLocation(); - datacenter_id = documentLocation.dc_id; location.id = documentLocation.id; location.access_hash = documentLocation.access_hash; + datacenter_id = documentLocation.dc_id; } - totalBytesCount = documentLocation.size; - ext = FileLoader.getDocumentFileName(documentLocation); - int idx; - if (ext == null || (idx = ext.lastIndexOf(".")) == -1) { - ext = ""; - } else { - ext = ext.substring(idx); - if (ext.length() <= 1) { + if (totalBytesCount <= 0) { + totalBytesCount = documentLocation.size; + } + if (ext == null) { + ext = FileLoader.getDocumentFileName(documentLocation); + int idx; + if (ext == null || (idx = ext.lastIndexOf(".")) == -1) { ext = ""; + } else { + ext = ext.substring(idx); + if (ext.length() <= 1) { + ext = ""; + } + } + + if(ApplicationLoader.KEEP_ORIGINAL_FILENAME && !ext.contains("webp") && !FileLoader.isGif(documentLocation)) { + orgName = FileLoader.getDocName(documentLocation); } - } - if(ApplicationLoader.KEEP_ORIGINAL_FILENAME && !ext.contains("webp")){ - orgName = FileLoader.getDocName(documentLocation); } } @@ -200,7 +206,7 @@ public class FileLoadOperation { String fileNameTemp; String fileNameIv = null; if (location.volume_id != 0 && location.local_id != 0) { - fileNameTemp = location.volume_id + "_" + location.local_id + "_temp." + ext; + fileNameTemp = location.volume_id + "_" + location.local_id + ".temp"; fileNameFinal = location.volume_id + "_" + location.local_id + "." + ext; if (key != null) { fileNameIv = location.volume_id + "_" + location.local_id + ".iv"; @@ -216,7 +222,7 @@ public class FileLoadOperation { return; } } else { - fileNameTemp = datacenter_id + "_" + location.id + "_temp" + ext; + fileNameTemp = datacenter_id + "_" + location.id + ".temp"; fileNameFinal = datacenter_id + "_" + location.id + ext; if (key != null) { fileNameIv = datacenter_id + "_" + location.id + ".iv"; @@ -252,12 +258,11 @@ public class FileLoadOperation { if (!cacheFileFinal.exists()) { cacheFileTemp = new File(tempPath, fileNameTemp); if (cacheFileTemp.exists()) { - downloadedBytes = (int)cacheFileTemp.length(); + downloadedBytes = (int) cacheFileTemp.length(); nextDownloadOffset = downloadedBytes = downloadedBytes / currentDownloadChunkSize * currentDownloadChunkSize; } - //if (BuildVars.DEBUG_VERSION) { - if (BuildConfig.DEBUG) { + if (BuildVars.DEBUG_VERSION) { FileLog.d("tmessages", "start loading file to temp = " + cacheFileTemp + " final = " + cacheFileFinal); } @@ -341,6 +346,11 @@ public class FileLoadOperation { private void cleanup() { try { if (fileOutputStream != null) { + try { + fileOutputStream.getChannel().close(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } fileOutputStream.close(); fileOutputStream = null; } @@ -357,7 +367,8 @@ public class FileLoadOperation { FileLog.e("tmessages", e); } if (delayedRequestInfos != null) { - for (RequestInfo requestInfo : delayedRequestInfos) { + for (int a = 0; a < delayedRequestInfos.size(); a++) { + RequestInfo requestInfo = delayedRequestInfos.get(a); if (requestInfo.response != null) { requestInfo.response.disableFree = false; requestInfo.response.freeResources(); @@ -375,18 +386,33 @@ public class FileLoadOperation { cleanup(); if (cacheIvTemp != null) { cacheIvTemp.delete(); + cacheIvTemp = null; } if (cacheFileTemp != null) { - if (!cacheFileTemp.renameTo(cacheFileFinal)) { - //if (BuildVars.DEBUG_VERSION) { - if (BuildConfig.DEBUG) { - FileLog.e("tmessages", "unable to rename temp = " + cacheFileTemp + " to final = " + cacheFileFinal); + boolean renameResult = cacheFileTemp.renameTo(cacheFileFinal); + if (!renameResult) { + if (BuildVars.DEBUG_VERSION) { + FileLog.e("tmessages", "unable to rename temp = " + cacheFileTemp + " to final = " + cacheFileFinal + " retry = " + renameRetryCount); + } + renameRetryCount++; + if (renameRetryCount < 3) { + state = stateDownloading; + Utilities.stageQueue.postRunnable(new Runnable() { + @Override + public void run() { + try { + onFinishLoadingFile(); + } catch (Exception e) { + delegate.didFailedLoadingFile(FileLoadOperation.this, 0); + } + } + }, 200); + return; } cacheFileFinal = cacheFileTemp; } } - //if (BuildVars.DEBUG_VERSION) { - if (BuildConfig.DEBUG) { + if (BuildVars.DEBUG_VERSION) { FileLog.e("tmessages", "finished downloading file to " + cacheFileFinal); } delegate.didFinishLoadingFile(FileLoadOperation.this, cacheFileFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index d24e2e6a..da37a22c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -3,11 +3,13 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; +import android.util.Log; + import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -84,6 +86,10 @@ public class FileLoader { mediaDirs = dirs; } + public File checkDirectory(int type) { + return mediaDirs.get(type); + } + public File getDirectory(int type) { File dir = mediaDirs.get(type); if (dir == null && type != MEDIA_DIR_CACHE) { @@ -703,7 +709,8 @@ public class FileLoader { if (document.file_name != null) { return document.file_name; } - for (TLRPC.DocumentAttribute documentAttribute : document.attributes) { + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute documentAttribute = document.attributes.get(a); if (documentAttribute instanceof TLRPC.TL_documentAttributeFilename) { return documentAttribute.file_name; } @@ -722,22 +729,25 @@ public class FileLoader { return video.dc_id + "_" + video.id + "." + (ext != null ? ext : "mp4"); } else if (attach instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) attach; - String docExt = getDocumentFileName(document); - int idx; - if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { - docExt = ""; - } else { - docExt = docExt.substring(idx); + String docExt = null; + if (docExt == null) { + docExt = getDocumentFileName(document); + int idx; + if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { + docExt = ""; + } else { + docExt = docExt.substring(idx); + } } if (docExt.length() > 1) { - if(ApplicationLoader.KEEP_ORIGINAL_FILENAME && !docExt.contains("webp"))return getDocName(document); //Plus + if(ApplicationLoader.KEEP_ORIGINAL_FILENAME && !docExt.contains("webp") && !isGif(document))return getDocName(document); //Plus return document.dc_id + "_" + document.id + docExt; } else { return document.dc_id + "_" + document.id; } } else if (attach instanceof TLRPC.PhotoSize) { TLRPC.PhotoSize photo = (TLRPC.PhotoSize) attach; - if (photo.location == null) { + if (photo.location == null || photo.location instanceof TLRPC.TL_fileLocationUnavailable) { return ""; } return photo.location.volume_id + "_" + photo.location.local_id + "." + (ext != null ? ext : "jpg"); @@ -745,43 +755,63 @@ public class FileLoader { TLRPC.Audio audio = (TLRPC.Audio) attach; return audio.dc_id + "_" + audio.id + "." + (ext != null ? ext : "ogg"); } else if (attach instanceof TLRPC.FileLocation) { + if (attach instanceof TLRPC.TL_fileLocationUnavailable) { + return ""; + } TLRPC.FileLocation location = (TLRPC.FileLocation) attach; return location.volume_id + "_" + location.local_id + "." + (ext != null ? ext : "jpg"); } return ""; } //Plus - public static String getAttachFileName(TLObject attach, boolean out) { + + public static boolean isGif(TLRPC.Document document){ + String s = getDocumentFileName(document); + if(s.contains(".mp4") || s.contains(".gif")){ + //if(s.contains("giphy.") || s.contains("animation.") || s.contains("gif.")){ + return true; + //} + } + return false; + } + + public static String getAttachFileName(TLObject attach, String ext, boolean out) { if (attach instanceof TLRPC.Video) { TLRPC.Video video = (TLRPC.Video) attach; - return video.dc_id + "_" + video.id + "." + ("mp4"); + return video.dc_id + "_" + video.id + "." + (ext != null ? ext : "mp4"); } else if (attach instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) attach; - String docExt = getDocumentFileName(document); - int idx; - if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { - docExt = ""; - } else { - docExt = docExt.substring(idx); + String docExt = null; + if (docExt == null) { + docExt = getDocumentFileName(document); + int idx; + if (docExt == null || (idx = docExt.lastIndexOf(".")) == -1) { + docExt = ""; + } else { + docExt = docExt.substring(idx); + } } if (docExt.length() > 1) { - if(!out && ApplicationLoader.KEEP_ORIGINAL_FILENAME && !docExt.contains("webp"))return getDocName(document); + if(!out && ApplicationLoader.KEEP_ORIGINAL_FILENAME && !docExt.contains("webp") && !isGif(document))return getDocName(document); return document.dc_id + "_" + document.id + docExt; } else { return document.dc_id + "_" + document.id; } } else if (attach instanceof TLRPC.PhotoSize) { TLRPC.PhotoSize photo = (TLRPC.PhotoSize) attach; - if (photo.location == null) { + if (photo.location == null || photo.location instanceof TLRPC.TL_fileLocationUnavailable) { return ""; } - return photo.location.volume_id + "_" + photo.location.local_id + "." + ( "jpg"); + return photo.location.volume_id + "_" + photo.location.local_id + "." + (ext != null ? ext : "jpg"); } else if (attach instanceof TLRPC.Audio) { TLRPC.Audio audio = (TLRPC.Audio) attach; - return audio.dc_id + "_" + audio.id + "." + ( "ogg"); + return audio.dc_id + "_" + audio.id + "." + (ext != null ? ext : "ogg"); } else if (attach instanceof TLRPC.FileLocation) { + if (attach instanceof TLRPC.TL_fileLocationUnavailable) { + return ""; + } TLRPC.FileLocation location = (TLRPC.FileLocation) attach; - return location.volume_id + "_" + location.local_id + "." + ( "jpg"); + return location.volume_id + "_" + location.local_id + "." + (ext != null ? ext : "jpg"); } return ""; } @@ -810,7 +840,7 @@ public class FileLoader { return name; } - public void deleteFiles(final ArrayList files) { + public void deleteFiles(final ArrayList files, final int type) { if (files == null || files.isEmpty()) { return; } @@ -829,17 +859,20 @@ public class FileLoader { } } try { - File qFile = new File(file.getPath(), "q_" + file.getName()); + File qFile = new File(file.getParentFile(), "q_" + file.getName()); if (qFile.exists()) { - if (!file.delete()) { - file.deleteOnExit(); + if (!qFile.delete()) { + qFile.deleteOnExit(); } } } catch (Exception e) { FileLog.e("tmessages", e); } } - } + if (type == 2) { + ImageLoader.getInstance().clearMemory(); + } +} }); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 27df53a6..0f372983 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; @@ -40,8 +40,7 @@ public class FileLog { } public FileLog() { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } dateFormat = FastDateFormat.getInstance("dd_MM_yyyy_HH_mm_ss", Locale.US); @@ -88,8 +87,7 @@ public class FileLog { } public static void e(final String tag, final String message, final Throwable exception) { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } Log.e(tag, message, exception); @@ -110,8 +108,7 @@ public class FileLog { } public static void e(final String tag, final String message) { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } Log.e(tag, message); @@ -131,8 +128,7 @@ public class FileLog { } public static void e(final String tag, final Throwable e) { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } e.printStackTrace(); @@ -158,8 +154,7 @@ public class FileLog { } public static void d(final String tag, final String message) { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } Log.d(tag, message); @@ -179,8 +174,7 @@ public class FileLog { } public static void w(final String tag, final String message) { - //if (!BuildVars.DEBUG_VERSION) { - if (!BuildConfig.DEBUG) { + if (!BuildVars.DEBUG_VERSION) { return; } Log.w(tag, message); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index e60cc289..0cdf5e64 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java index ac218a10..594a6320 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index ffaa8848..6cda1ba7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; @@ -68,7 +68,7 @@ public class UserConfig { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("registeredForPush", registeredForPush); - editor.putString("pushString", pushString); + editor.putString("pushString2", pushString); editor.putInt("lastSendMessageId", lastSendMessageId); editor.putInt("lastLocalId", lastLocalId); editor.putString("contactsHash", contactsHash); @@ -182,7 +182,7 @@ public class UserConfig { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); registeredForPush = preferences.getBoolean("registeredForPush", false); - pushString = preferences.getString("pushString", ""); + pushString = preferences.getString("pushString2", ""); lastSendMessageId = preferences.getInt("lastSendMessageId", -210000); lastLocalId = preferences.getInt("lastLocalId", -210000); contactsHash = preferences.getString("contactsHash", ""); @@ -209,7 +209,7 @@ public class UserConfig { } else { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); registeredForPush = preferences.getBoolean("registeredForPush", false); - pushString = preferences.getString("pushString", ""); + pushString = preferences.getString("pushString2", ""); lastSendMessageId = preferences.getInt("lastSendMessageId", -210000); lastLocalId = preferences.getInt("lastLocalId", -210000); contactsHash = preferences.getString("contactsHash", ""); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 2e5796b2..ca7279cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.messenger; @@ -64,7 +64,8 @@ public class Utilities { public native static void loadBitmap(String path, Bitmap bitmap, int scale, int width, int height, int stride); public native static int pinBitmap(Bitmap bitmap); - public native static void blurBitmap(Object bitmap, int radius, int unpin); + public native static int unpinBitmap(Bitmap bitmap); + public native static void blurBitmap(Object bitmap, int radius, int unpin, int width, int height, int stride); public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer); public native static boolean loadWebpImage(Bitmap bitmap, ByteBuffer buffer, int len, BitmapFactory.Options options, boolean unpin); public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap); @@ -91,6 +92,23 @@ public class Utilities { return val; } + public static Long parseLong(String value) { + if (value == null) { + return 0L; + } + Long val = 0L; + try { + Matcher matcher = pattern.matcher(value); + if (matcher.find()) { + String num = matcher.group(0); + val = Long.parseLong(num); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return val; + } + public static String parseIntToString(String value) { Matcher matcher = pattern.matcher(value); if (matcher.find()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index e0300ccd..263f9423 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index fdf6f29e..a3aa8f87 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index ee58185b..7a4ab56a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index 5e478a02..10d81a05 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; @@ -436,7 +436,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { searchField.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_SEARCH || event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + if (/*actionId == EditorInfo.IME_ACTION_SEARCH || */event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { AndroidUtilities.hideKeyboard(searchField); if (listener != null) { listener.onSearchPressed(searchField); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 4fe5781f..c2e5d39d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ //Thanks to https://github.com/JakeWharton/ActionBarSherlock/ diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 5ecd758e..18de8364 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java index 85f32fe7..47a41063 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; @@ -453,37 +453,39 @@ public class DrawerLayoutContainer extends FrameLayout { child.measure(drawerWidthSpec, drawerHeightSpec); } } - //getDrawerLayout().setBackgroundColor(AndroidUtilities.getIntDef("drawerListColor",0xffffffff)); //Plus + //Plus updateListBG(); } private void updateListBG(){ - SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); - int mainColor = themePrefs.getInt("drawerListColor", 0xffffffff); - int value = themePrefs.getInt("drawerRowGradient", 0); - boolean b = true;//themePrefs.getBoolean("drawerRowGradientListCheck", false); - if(value > 0 && b) { - GradientDrawable.Orientation go; - switch(value) { - case 2: - go = GradientDrawable.Orientation.LEFT_RIGHT; - break; - case 3: - go = GradientDrawable.Orientation.TL_BR; - break; - case 4: - go = GradientDrawable.Orientation.BL_TR; - break; - default: - go = GradientDrawable.Orientation.TOP_BOTTOM; - } + if(getDrawerLayout() != null) { + SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int mainColor = themePrefs.getInt("drawerListColor", 0xffffffff); + int value = themePrefs.getInt("drawerRowGradient", 0); + boolean b = true;//themePrefs.getBoolean("drawerRowGradientListCheck", false); + if (value > 0 && b) { + GradientDrawable.Orientation go; + switch (value) { + case 2: + go = GradientDrawable.Orientation.LEFT_RIGHT; + break; + case 3: + go = GradientDrawable.Orientation.TL_BR; + break; + case 4: + go = GradientDrawable.Orientation.BL_TR; + break; + default: + go = GradientDrawable.Orientation.TOP_BOTTOM; + } - int gradColor = themePrefs.getInt("drawerRowGradientColor", 0xffffffff); - int[] colors = new int[]{mainColor, gradColor}; - GradientDrawable gd = new GradientDrawable(go, colors); - getDrawerLayout().setBackgroundDrawable(gd); - }else{ - getDrawerLayout().setBackgroundColor(mainColor); + int gradColor = themePrefs.getInt("drawerRowGradientColor", 0xffffffff); + int[] colors = new int[]{mainColor, gradColor}; + GradientDrawable gd = new GradientDrawable(go, colors); + getDrawerLayout().setBackgroundDrawable(gd); + } else { + getDrawerLayout().setBackgroundColor(mainColor); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java index 3543bbe7..1ae9b0b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java index 57bd70eb..ae94e8f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java index bfd0457e..ddae75a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java index f659249b..9324cd9f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java index a6b49329..b09a0940 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java index 91049dbe..183076a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index 5bf34021..c7ff8a43 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -3,26 +3,24 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; import android.content.Context; import android.content.SharedPreferences; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.view.View; import android.view.ViewGroup; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.ui.Cells.DividerCell; @@ -231,33 +229,19 @@ public class ContactsAdapter extends BaseSectionsAdapter { TextCell actionCell = (TextCell) convertView; actionCell.setTextColor(cColorBlack); if (needPhonebook) { - //actionCell.setTextAndIcon(LocaleController.getString("InviteFriends", R.string.InviteFriends), R.drawable.menu_invite); - Drawable invite = mContext.getResources().getDrawable(R.drawable.menu_invite); - invite.setColorFilter(iconsColor, PorterDuff.Mode.SRC_IN); - actionCell.setTextAndIcon(LocaleController.getString("InviteFriends", R.string.InviteFriends), invite); + actionCell.setTextAndIcon(LocaleController.getString("InviteFriends", R.string.InviteFriends), R.drawable.menu_invite); } else if (isAdmin) { - //actionCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.menu_invite); - Drawable invite = mContext.getResources().getDrawable(R.drawable.menu_invite); - invite.setColorFilter(iconsColor, PorterDuff.Mode.SRC_IN); - actionCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), invite); + actionCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.menu_invite); } else { if (position == 0) { - //actionCell.setTextAndIcon(LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_newgroup); - Drawable newGroup = mContext.getResources().getDrawable(R.drawable.menu_newgroup); - newGroup.setColorFilter(iconsColor, PorterDuff.Mode.SRC_IN); - actionCell.setTextAndIcon(LocaleController.getString("NewGroup", R.string.NewGroup), newGroup); + actionCell.setTextAndIcon(LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_newgroup); } else if (position == 1) { - //actionCell.setTextAndIcon(LocaleController.getString("NewSecretChat", R.string.NewSecretChat), R.drawable.menu_secret); - Drawable secret = mContext.getResources().getDrawable(R.drawable.menu_secret); - secret.setColorFilter(iconsColor, PorterDuff.Mode.SRC_IN); - actionCell.setTextAndIcon(LocaleController.getString("NewSecretChat", R.string.NewSecretChat), secret); + actionCell.setTextAndIcon(LocaleController.getString("NewSecretChat", R.string.NewSecretChat), R.drawable.menu_secret); } else if (position == 2) { - //actionCell.setTextAndIcon(LocaleController.getString("NewChannel", R.string.NewChannel), R.drawable.menu_broadcast); - Drawable broadcast = mContext.getResources().getDrawable(R.drawable.menu_broadcast); - broadcast.setColorFilter(iconsColor, PorterDuff.Mode.SRC_IN); - actionCell.setTextAndIcon(LocaleController.getString("NewChannel", R.string.NewChannel), broadcast); + actionCell.setTextAndIcon(LocaleController.getString("NewChannel", R.string.NewChannel), R.drawable.menu_broadcast); } } + actionCell.setIconColor(iconsColor); } else if (type == 1) { if (convertView == null) { convertView = new TextCell(mContext); @@ -276,6 +260,7 @@ public class ContactsAdapter extends BaseSectionsAdapter { } else if (type == 0) { if (convertView == null) { convertView = new UserCell(mContext, 58, 1); + ((UserCell) convertView).setStatusColors(0xffa8a8a8, 0xff3b84c0); convertView.setTag("Contacts"); } updateViewColor(convertView); @@ -297,7 +282,6 @@ public class ContactsAdapter extends BaseSectionsAdapter { } } } - //parent.setBackgroundColor(themePrefs.getInt("contactsRowColor", 0xffffffff)); //Plus updateListBG(parent); return convertView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java index 216f27c8..4183abe3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java index 0282d9df..d3cd6d2b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index d9f0972e..e3631429 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -3,11 +3,12 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; +import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.graphics.drawable.GradientDrawable; @@ -17,12 +18,16 @@ import android.view.ViewGroup; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.LoadingCell; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; public class DialogsAdapter extends RecyclerView.Adapter { @@ -53,16 +58,205 @@ public class DialogsAdapter extends RecyclerView.Adapter { } private ArrayList getDialogsArray() { + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); if (dialogsType == 0) { + boolean hideTabs = plusPreferences.getBoolean("hideTabs", false); + int sort = plusPreferences.getInt("sortAll", 0); + if(sort == 0 || hideTabs){ + sortDefault(MessagesController.getInstance().dialogs); + }else{ + sortUnread(MessagesController.getInstance().dialogs); + } return MessagesController.getInstance().dialogs; } else if (dialogsType == 1) { return MessagesController.getInstance().dialogsServerOnly; } else if (dialogsType == 2) { return MessagesController.getInstance().dialogsGroupsOnly; } + //plus + else if (dialogsType == 3) { + int sort = plusPreferences.getInt("sortUsers", 0); + if(sort == 0){ + sortUsersDefault(); + }else{ + sortUsersByStatus(); + } + return MessagesController.getInstance().dialogsUsers; + } else if (dialogsType == 4) { + int sort = plusPreferences.getInt("sortGroups", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsGroups); + }else{ + sortUnread(MessagesController.getInstance().dialogsGroups); + } + return MessagesController.getInstance().dialogsGroups; + } else if (dialogsType == 5) { + int sort = plusPreferences.getInt("sortChannels", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsChannels); + }else{ + sortUnread(MessagesController.getInstance().dialogsChannels); + } + return MessagesController.getInstance().dialogsChannels; + } else if (dialogsType == 6) { + int sort = plusPreferences.getInt("sortBots", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsBots); + }else{ + sortUnread(MessagesController.getInstance().dialogsBots); + } + return MessagesController.getInstance().dialogsBots; + } else if (dialogsType == 7) { + int sort = plusPreferences.getInt("sortSGroups", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsMegaGroups); + }else{ + sortUnread(MessagesController.getInstance().dialogsMegaGroups); + } + return MessagesController.getInstance().dialogsMegaGroups; + } else if (dialogsType == 8) { + int sort = plusPreferences.getInt("sortFavs", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsFavs); + }else{ + sortUnread(MessagesController.getInstance().dialogsFavs); + } + return MessagesController.getInstance().dialogsFavs; + } else if (dialogsType == 9) { + int sort = plusPreferences.getInt("sortGroups", 0); + if(sort == 0){ + sortDefault(MessagesController.getInstance().dialogsGroupsAll); + }else{ + sortUnread(MessagesController.getInstance().dialogsGroupsAll); + } + return MessagesController.getInstance().dialogsGroupsAll; + } + // return null; } + //plus + private void sortUsersByStatus(){ + Collections.sort(MessagesController.getInstance().dialogsUsers, new Comparator() { + @Override + public int compare(TLRPC.Dialog tl_dialog, TLRPC.Dialog tl_dialog2) { + TLRPC.User user1 = MessagesController.getInstance().getUser((int) tl_dialog2.id); + TLRPC.User user2 = MessagesController.getInstance().getUser((int) tl_dialog.id); + int status1 = 0; + int status2 = 0; + if (user1 != null && user1.status != null) { + if (user1.id == UserConfig.getClientUserId()) { + status1 = ConnectionsManager.getInstance().getCurrentTime() + 50000; + } else { + status1 = user1.status.expires; + } + } + if (user2 != null && user2.status != null) { + if (user2.id == UserConfig.getClientUserId()) { + status2 = ConnectionsManager.getInstance().getCurrentTime() + 50000; + } else { + status2 = user2.status.expires; + } + } + if (status1 > 0 && status2 > 0) { + if (status1 > status2) { + return 1; + } else if (status1 < status2) { + return -1; + } + return 0; + } else if (status1 < 0 && status2 < 0) { + if (status1 > status2) { + return 1; + } else if (status1 < status2) { + return -1; + } + return 0; + } else if (status1 < 0 && status2 > 0 || status1 == 0 && status2 != 0) { + return -1; + } else if (status2 < 0 && status1 > 0 || status2 == 0 && status1 != 0) { + return 1; + } + return 0; + } + }); + } + private void sortDefault(ArrayList dialogs){ + Collections.sort(dialogs, new Comparator() { + @Override + public int compare(TLRPC.Dialog dialog, TLRPC.Dialog dialog2) { + if (dialog.last_message_date == dialog2.last_message_date) { + return 0; + } else if (dialog.last_message_date < dialog2.last_message_date) { + return 1; + } else { + return -1; + } + } + }); + } + + private void sortUnread(ArrayList dialogs){ + Collections.sort(dialogs, new Comparator() { + @Override + public int compare(TLRPC.Dialog dialog, TLRPC.Dialog dialog2) { + if (dialog.unread_count == dialog2.unread_count) { + return 0; + } else if (dialog.unread_count < dialog2.unread_count) { + return 1; + } else { + return -1; + } + } + }); + } + + private void sortUsersDefault(){ + Collections.sort(MessagesController.getInstance().dialogsUsers, new Comparator() { + @Override + public int compare(TLRPC.Dialog dialog, TLRPC.Dialog dialog2) { + if (dialog.last_message_date == dialog2.last_message_date) { + return 0; + } else if (dialog.last_message_date < dialog2.last_message_date) { + return 1; + } else { + return -1; + } + } + }); + } + + /*private void sortAllDefault(ArrayList dialogs){ + Collections.sort(dialogs, new Comparator() { + @Override + public int compare(TLRPC.Dialog dialog, TLRPC.Dialog dialog2) { + if (dialog.last_message_date == dialog2.last_message_date) { + return 0; + } else if (dialog.last_message_date < dialog2.last_message_date) { + return 1; + } else { + return -1; + } + } + }); + } + + private void sortAllUnread(ArrayList dialogs){ + Collections.sort(dialogs, new Comparator() { + @Override + public int compare(TLRPC.Dialog dialog, TLRPC.Dialog dialog2) { + if (dialog.unread_count == dialog2.unread_count) { + return 0; + } else if (dialog.unread_count < dialog2.unread_count) { + return 1; + } else { + return -1; + } + } + }); + }*/ + // @Override public int getItemCount() { int count = getDialogsArray().size(); @@ -97,7 +291,7 @@ public class DialogsAdapter extends RecyclerView.Adapter { } else if (viewType == 1) { view = new LoadingCell(mContext); } - + if(dialogsType > 2 && viewType == 1)view.setVisibility(View.GONE); SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); int mainColor = themePrefs.getInt("chatsRowColor", 0xffffffff); int value = themePrefs.getInt("chatsRowGradient", 0); @@ -125,7 +319,6 @@ public class DialogsAdapter extends RecyclerView.Adapter { }else{ viewGroup.setBackgroundColor(mainColor); } - //viewGroup.setBackgroundColor(mainColor); return new Holder(view); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index c5347772..725d779a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index fce3bc38..7a6742ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; @@ -41,10 +41,10 @@ public class DrawerLayoutAdapter extends BaseAdapter { private int themesRow = 7; private int themingRow = 8; private int settingsRow = 9; - private int channelRow = 10; - private int communityRow = 11; - private int versionRow = 12; - + private int plusSettingsRow = 10; + private int channelRow = 11; + private int communityRow = 12; + private int versionRow = 13; //private int rowCount = 0; @@ -65,7 +65,7 @@ public class DrawerLayoutAdapter extends BaseAdapter { @Override public int getCount() { //return UserConfig.isClientActivated() ? 10 : 0; - return UserConfig.isClientActivated() ? 13 : 0; + return UserConfig.isClientActivated() ? versionRow + 1 : 0; } @Override @@ -140,6 +140,8 @@ public class DrawerLayoutAdapter extends BaseAdapter { actionCell.setTextAndIcon(LocaleController.getString("DownloadThemes", R.string.DownloadThemes), R.drawable.menu_themes); } else if (i == themingRow) { actionCell.setTextAndIcon(LocaleController.getString("Theming", R.string.Theming), R.drawable.menu_theming); + } else if (i == plusSettingsRow) { + actionCell.setTextAndIcon(LocaleController.getString("Theming", R.string.PlusSettings), R.drawable.menu_plus); } else if (i == settingsRow) { actionCell.setTextAndIcon(LocaleController.getString("Settings", R.string.Settings), R.drawable.menu_settings); } else if (i == channelRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index dbdadeba..a94c1e43 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java index 94669e13..eea4d6f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index 939f86f3..d528b6d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; @@ -12,10 +12,21 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.SQLite.SQLitePreparedStatement; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.UserObject; +import org.telegram.messenger.support.widget.LinearLayoutManager; +import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.RequestDelegate; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.MentionCell; import java.util.ArrayList; @@ -23,19 +34,31 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -public class MentionsAdapter extends BaseSearchAdapter { +public class MentionsAdapter extends BaseSearchAdapterRecycler { public interface MentionsAdapterDelegate { void needChangePanelVisibility(boolean show); + void onContextSearch(boolean searching); + void onContextClick(TLRPC.BotInlineResult result); + } + + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } } private Context mContext; private TLRPC.ChatFull info; + private ArrayList botRecent; private ArrayList searchResultUsernames; private ArrayList searchResultHashtags; private ArrayList searchResultCommands; private ArrayList searchResultCommandsHelp; private ArrayList searchResultCommandsUsers; + private ArrayList searchResultBotContext; + private HashMap searchResultBotContextById; private MentionsAdapterDelegate delegate; private HashMap botInfo; private int resultStartPosition; @@ -44,8 +67,20 @@ public class MentionsAdapter extends BaseSearchAdapter { private int lastPosition; private ArrayList messages; private boolean needUsernames = true; + private boolean needBotContext = true; private boolean isDarkTheme; private int botsCount; + private boolean loadingBotRecent; + + private String searchingContextUsername; + private String searchingContextQuery; + private String nextQueryOffset; + private int contextUsernameReqid; + private int contextQueryReqid; + private boolean noUserName; + private TLRPC.User foundContextBot; + private boolean contextMedia; + private Runnable contextQueryRunnable; public MentionsAdapter(Context context, boolean isDarkTheme, MentionsAdapterDelegate delegate) { mContext = context; @@ -60,10 +95,122 @@ public class MentionsAdapter extends BaseSearchAdapter { } } + private void loadBotRecent() { + if (loadingBotRecent) { + return; + } + loadingBotRecent = true; + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT id FROM bot_recent ORDER BY date DESC"); + ArrayList uids = null; + while (cursor.next()) { + if (uids == null) { + uids = new ArrayList<>(); + } + uids.add(cursor.intValue(0)); + } + cursor.dispose(); + if (uids != null) { + final ArrayList users = MessagesStorage.getInstance().getUsers(uids); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + botRecent = users; + loadingBotRecent = false; + if (lastText != null) { + searchUsernameOrHashtag(lastText, lastPosition, messages); + } + } + }); + } else { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + loadingBotRecent = false; + } + }); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + public void addRecentBot() { + if (foundContextBot == null) { + return; + } + if (botRecent == null) { + botRecent = new ArrayList<>(); + } else { + for (int a = 0; a < botRecent.size(); a++) { + TLRPC.User user = botRecent.get(a); + if (user.id == foundContextBot.id) { + botRecent.remove(a); + break; + } + } + } + botRecent.add(0, foundContextBot); + final int uid = foundContextBot.id; + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO bot_recent VALUES(?, ?)"); + state.requery(); + state.bindInteger(1, uid); + state.bindInteger(2, (int) (System.currentTimeMillis() / 1000)); + state.step(); + state.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + public void removeRecentBot(final TLRPC.User bot) { + if (botRecent == null || bot == null) { + return; + } + for (int a = 0; a < botRecent.size(); a++) { + TLRPC.User user = botRecent.get(a); + if (user.id == bot.id) { + botRecent.remove(a); + if (botRecent.isEmpty()) { + botRecent = null; + } + break; + } + } + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + MessagesStorage.getInstance().getDatabase().executeFast("DELETE FROM bot_recent WHERE id = " + bot.id).stepThis().dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + public void setNeedUsernames(boolean value) { needUsernames = value; } + public void setNeedBotContext(boolean value) { + needBotContext = value; + if (needBotContext) { + loadBotRecent(); + } + } + public void setBotInfo(HashMap info) { botInfo = info; } @@ -90,8 +237,210 @@ public class MentionsAdapter extends BaseSearchAdapter { } } + public int getContextBotId() { + return foundContextBot != null ? foundContextBot.id : 0; + } + + private void searchForContextBot(final String username, final String query) { + searchResultBotContext = null; + searchResultBotContextById = null; + notifyDataSetChanged(); + if (foundContextBot != null) { + delegate.needChangePanelVisibility(false); + } + if (contextQueryRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(contextQueryRunnable); + contextQueryRunnable = null; + } + if (username == null || username.length() == 0 || searchingContextUsername != null && !searchingContextUsername.equals(username)) { + if (contextUsernameReqid != 0) { + ConnectionsManager.getInstance().cancelRequest(contextUsernameReqid, true); + contextUsernameReqid = 0; + } + if (contextQueryReqid != 0) { + ConnectionsManager.getInstance().cancelRequest(contextQueryReqid, true); + contextQueryReqid = 0; + } + foundContextBot = null; + searchingContextUsername = null; + searchingContextQuery = null; + noUserName = false; + if (delegate != null) { + delegate.onContextSearch(false); + } + if (username == null || username.length() == 0) { + return; + } + } + if (query == null) { + if (contextQueryReqid != 0) { + ConnectionsManager.getInstance().cancelRequest(contextQueryReqid, true); + contextQueryReqid = 0; + } + searchingContextQuery = null; + if (delegate != null) { + delegate.onContextSearch(false); + } + return; + } + if (delegate != null) { + if (foundContextBot != null) { + delegate.onContextSearch(true); + } else if (username.equals("gif")) { + searchingContextUsername = "gif"; + delegate.onContextSearch(false); + } + } + searchingContextQuery = query; + contextQueryRunnable = new Runnable() { + @Override + public void run() { + if (contextQueryRunnable != this) { + return; + } + contextQueryRunnable = null; + if (foundContextBot != null || noUserName) { + if (noUserName) { + return; + } + searchForContextBotResults(foundContextBot, query, ""); + } else { + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = searchingContextUsername = username; + contextUsernameReqid = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (searchingContextUsername == null || !searchingContextUsername.equals(username)) { + return; + } + contextUsernameReqid = 0; + foundContextBot = null; + if (error == null) { + TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; + if (!res.users.isEmpty()) { + TLRPC.User user = res.users.get(0); + if (user.bot && user.bot_inline_placeholder != null) { + MessagesController.getInstance().putUser(user, false); + MessagesStorage.getInstance().putUsersAndChats(res.users, null, true, true); + foundContextBot = user; + } + } + } + if (foundContextBot == null) { + noUserName = true; + } else { + if (delegate != null) { + delegate.onContextSearch(true); + } + searchForContextBotResults(foundContextBot, searchingContextQuery, ""); + } + } + }); + + } + }); + } + } + }; + AndroidUtilities.runOnUIThread(contextQueryRunnable, 400); + } + + public int getOrientation() { + return searchResultBotContext != null && !searchResultBotContext.isEmpty() && contextMedia ? LinearLayoutManager.HORIZONTAL : LinearLayoutManager.VERTICAL; + } + + public String getBotCaption() { + if (foundContextBot != null) { + return foundContextBot.bot_inline_placeholder; + } else if (searchingContextUsername != null && searchingContextUsername.equals("gif")) { + return "Search GIFs"; + } + return null; + } + + public void searchForContextBotForNextOffset() { + if (contextQueryReqid != 0 || nextQueryOffset == null || nextQueryOffset.length() == 0 || foundContextBot == null || searchingContextQuery == null) { + return; + } + searchForContextBotResults(foundContextBot, searchingContextQuery, nextQueryOffset); + } + + private void searchForContextBotResults(TLRPC.User user, final String query, final String offset) { + if (contextQueryReqid != 0) { + ConnectionsManager.getInstance().cancelRequest(contextQueryReqid, true); + contextQueryReqid = 0; + } + if (query == null || user == null) { + searchingContextQuery = null; + return; + } + TLRPC.TL_messages_getInlineBotResults req = new TLRPC.TL_messages_getInlineBotResults(); + req.bot = MessagesController.getInputUser(user); + req.query = query; + req.offset = offset; + contextQueryReqid = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (searchingContextQuery == null || !query.equals(searchingContextQuery)) { + return; + } + if (delegate != null) { + delegate.onContextSearch(false); + } + contextQueryReqid = 0; + if (error == null) { + TLRPC.TL_messages_botResults res = (TLRPC.TL_messages_botResults) response; + nextQueryOffset = res.next_offset; + if (searchResultBotContextById == null) { + searchResultBotContextById = new HashMap<>(); + } + for (int a = 0; a < res.results.size(); a++) { + TLRPC.BotInlineResult result = res.results.get(a); + if (searchResultBotContextById.containsKey(result.id) || !(result.document instanceof TLRPC.TL_document) && !(result.photo instanceof TLRPC.TL_photo) && result.content_url == null && result.send_message instanceof TLRPC.TL_botInlineMessageMediaAuto) { + res.results.remove(a); + a--; + } + result.query_id = res.query_id; + searchResultBotContextById.put(result.id, result); + } + boolean added = false; + if (searchResultBotContext == null || offset.length() == 0) { + searchResultBotContext = res.results; + } else { + added = true; + searchResultBotContext.addAll(res.results); + if (res.results.isEmpty()) { + nextQueryOffset = ""; + } + } + contextMedia = res.gallery; + searchResultHashtags = null; + searchResultUsernames = null; + searchResultCommands = null; + searchResultCommandsHelp = null; + searchResultCommandsUsers = null; + if (added) { + notifyItemRangeInserted(searchResultBotContext.size() - res.results.size(), res.results.size()); + } else { + notifyDataSetChanged(); + } + delegate.needChangePanelVisibility(!searchResultBotContext.isEmpty()); + } + } + }); + } + }, ConnectionsManager.RequestFlagFailOnServerErrors); + } + public void searchUsernameOrHashtag(String text, int position, ArrayList messageObjects) { if (text == null || text.length() == 0) { + searchForContextBot(null, null); delegate.needChangePanelVisibility(false); lastText = null; return; @@ -104,28 +453,68 @@ public class MentionsAdapter extends BaseSearchAdapter { StringBuilder result = new StringBuilder(); int foundType = -1; boolean hasIllegalUsernameCharacters = false; + if (needBotContext && text.charAt(0) == '@') { + int index = text.indexOf(' '); + if (index > 0) { + String username = text.substring(1, index); + if (username.length() >= 3) { + for (int a = 1; a < username.length(); a++) { + char ch = username.charAt(a); + if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_')) { + username = ""; + break; + } + } + } else { + username = ""; + } + String query = text.substring(index + 1); + if (username.length() > 0 && query.length() >= 0) { + searchForContextBot(username, query); + } else { + searchForContextBot(username, null); + } + } else { + searchForContextBot(null, null); + } + } else { + searchForContextBot(null, null); + } + int dogPostion = -1; for (int a = searchPostion; a >= 0; a--) { if (a >= text.length()) { continue; } char ch = text.charAt(a); if (a == 0 || text.charAt(a - 1) == ' ' || text.charAt(a - 1) == '\n') { - if (needUsernames && ch == '@') { - if (hasIllegalUsernameCharacters) { - delegate.needChangePanelVisibility(false); - return; - } - if (info == null) { + if (ch == '@') { + if (needUsernames || botRecent != null && a == 0) { + if (hasIllegalUsernameCharacters) { + delegate.needChangePanelVisibility(false); + return; + } + if (info == null && (botRecent == null || a != 0)) { + lastText = text; + lastPosition = position; + messages = messageObjects; + delegate.needChangePanelVisibility(false); + return; + } + if (loadingBotRecent) { + lastText = text; + lastPosition = position; + messages = messageObjects; + } + dogPostion = a; + foundType = 0; + resultStartPosition = a; + resultLength = result.length() + 1; + break; + } else if (loadingBotRecent) { lastText = text; lastPosition = position; messages = messageObjects; - delegate.needChangePanelVisibility(false); - return; } - foundType = 0; - resultStartPosition = a; - resultLength = result.length() + 1; - break; } else if (ch == '#') { if (!hashtagsLoadedFromDb) { loadRecentHashtags(); @@ -166,11 +555,21 @@ public class MentionsAdapter extends BaseSearchAdapter { } String usernameString = result.toString().toLowerCase(); ArrayList newResult = new ArrayList<>(); - if (info.participants != null) { + final HashMap newResultsHashMap = new HashMap<>(); + if (dogPostion == 0 && botRecent != null) { + for (int a = 0; a < botRecent.size(); a++) { + TLRPC.User user = botRecent.get(a); + if (user.username != null && user.username.length() > 0 && (usernameString.length() > 0 && user.username.toLowerCase().startsWith(usernameString) || usernameString.length() == 0)) { + newResult.add(user); + newResultsHashMap.put(user.id, user); + } + } + } + if (info != null && info.participants != null) { for (int a = 0; a < info.participants.participants.size(); a++) { TLRPC.ChatParticipant chatParticipant = info.participants.participants.get(a); TLRPC.User user = MessagesController.getInstance().getUser(chatParticipant.user_id); - if (user == null || UserObject.isUserSelf(user)) { + if (user == null || UserObject.isUserSelf(user) || newResultsHashMap.containsKey(user.id)) { continue; } if (user.username != null && user.username.length() > 0 && (usernameString.length() > 0 && user.username.toLowerCase().startsWith(usernameString) || usernameString.length() == 0)) { @@ -186,6 +585,13 @@ public class MentionsAdapter extends BaseSearchAdapter { Collections.sort(searchResultUsernames, new Comparator() { @Override public int compare(TLRPC.User lhs, TLRPC.User rhs) { + if (newResultsHashMap.containsKey(lhs.id) && newResultsHashMap.containsKey(rhs.id)) { + return 0; + } else if (newResultsHashMap.containsKey(lhs.id)) { + return -1; + } else if (newResultsHashMap.containsKey(rhs.id)) { + return 1; + } int lhsNum = users.indexOf(lhs.id); int rhsNum = users.indexOf(rhs.id); if (lhsNum != -1 && rhsNum != -1) { @@ -250,13 +656,10 @@ public class MentionsAdapter extends BaseSearchAdapter { } @Override - public int getViewTypeCount() { - return 1; - } - - @Override - public int getCount() { - if (searchResultUsernames != null) { + public int getItemCount() { + if (searchResultBotContext != null) { + return searchResultBotContext.size(); + } else if (searchResultUsernames != null) { return searchResultUsernames.size(); } else if (searchResultHashtags != null) { return searchResultHashtags.size(); @@ -266,41 +669,22 @@ public class MentionsAdapter extends BaseSearchAdapter { return 0; } - @Override - public boolean isEmpty() { - if (searchResultUsernames != null) { - return searchResultUsernames.isEmpty(); - } else if (searchResultHashtags != null) { - return searchResultHashtags.isEmpty(); - } else if (searchResultCommands != null) { - return searchResultCommands.isEmpty(); - } - return true; - } - @Override public int getItemViewType(int position) { - return 0; + if (searchResultBotContext != null) { + return 1; + } else { + return 0; + } } - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public boolean areAllItemsEnabled() { - return true; - } - - @Override - public boolean isEnabled(int position) { - return true; - } - - @Override public Object getItem(int i) { - if (searchResultUsernames != null) { + if (searchResultBotContext != null) { + if (i < 0 || i >= searchResultBotContext.size()) { + return null; + } + return searchResultBotContext.get(i); + } else if (searchResultUsernames != null) { if (i < 0 || i >= searchResultUsernames.size()) { return null; } @@ -334,19 +718,40 @@ public class MentionsAdapter extends BaseSearchAdapter { return searchResultCommands != null; } + public boolean isBotContext() { + return searchResultBotContext != null; + } + @Override - public View getView(int i, View view, ViewGroup viewGroup) { - if (view == null) { + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + if (viewType == 1) { + view = new ContextLinkCell(mContext); + ((ContextLinkCell) view).setDelegate(new ContextLinkCell.ContextLinkCellDelegate() { + @Override + public void didPressedImage(ContextLinkCell cell) { + delegate.onContextClick(cell.getResult()); + } + }); + } else { view = new MentionCell(mContext); ((MentionCell) view).setIsDarkTheme(isDarkTheme); } - if (searchResultUsernames != null) { - ((MentionCell) view).setUser(searchResultUsernames.get(i)); - } else if (searchResultHashtags != null) { - ((MentionCell) view).setText(searchResultHashtags.get(i)); - } else if (searchResultCommands != null) { - ((MentionCell) view).setBotCommand(searchResultCommands.get(i), searchResultCommandsHelp.get(i), searchResultCommandsUsers != null ? searchResultCommandsUsers.get(i) : null); + return new Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (searchResultBotContext != null) { + ((ContextLinkCell) holder.itemView).setLink(searchResultBotContext.get(position), contextMedia, position != searchResultBotContext.size() - 1); + } else { + if (searchResultUsernames != null) { + ((MentionCell) holder.itemView).setUser(searchResultUsernames.get(position)); + } else if (searchResultHashtags != null) { + ((MentionCell) holder.itemView).setText(searchResultHashtags.get(position)); + } else if (searchResultCommands != null) { + ((MentionCell) holder.itemView).setBotCommand(searchResultCommands.get(position), searchResultCommandsHelp.get(position), searchResultCommandsUsers != null ? searchResultCommandsUsers.get(position) : null); + } } - return view; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 3d734d62..08ae3a64 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 326e207a..22f692da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java index 232923c7..7ed17b2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java index d3215137..3f108795 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index aaf76695..22246bee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -24,19 +24,19 @@ import android.view.MotionEvent; import android.view.SoundEffectConstants; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.tgnet.TLRPC; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.ImageListActivity; import org.telegram.ui.PhotoViewer; +import org.telegram.ui.Components.AvatarDrawable; public class ChatActionCell extends BaseCell { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java index df142fdf..e7bbcb76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -15,18 +15,22 @@ import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; +import android.util.Log; import android.view.MotionEvent; import android.view.SoundEffectConstants; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildConfig; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; + import org.telegram.messenger.ImageLoader; -import org.telegram.messenger.MediaController; -import org.telegram.messenger.MessageObject; + import org.telegram.messenger.MessagesController; import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.FileLog; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.SeekBar; @@ -103,6 +107,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega buttonPressed = true; invalidate(); result = true; + radialProgress.swapBackground(getDrawableForCurrentState()); } } else if (buttonPressed) { if (event.getAction() == MotionEvent.ACTION_UP) { @@ -119,6 +124,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega invalidate(); } } + radialProgress.swapBackground(getDrawableForCurrentState()); } if (!result) { result = super.onTouchEvent(event); @@ -224,8 +230,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega if (cacheFile == null) { cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); } - //if (BuildVars.DEBUG_VERSION) { - if (BuildConfig.DEBUG) { + if (BuildVars.DEBUG_VERSION) { FileLog.d("tmessages", "looking for audio in " + cacheFile); } if (cacheFile.exists()) { @@ -348,10 +353,10 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega if (messageObject.isOutOwner()) { seekBar.type = 0; - radialProgress.setProgressColor(0xff87bf78); + //radialProgress.setProgressColor(0xff87bf78); } else { seekBar.type = 1; - radialProgress.setProgressColor(0xffa2b5c7); + //radialProgress.setProgressColor(0xffa2b5c7); } super.setMessageObject(messageObject); @@ -359,9 +364,32 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega updateButtonState(dataChanged); } + @Override + public void setCheckPressed(boolean value, boolean pressed) { + super.setCheckPressed(value, pressed); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + + @Override + public void setHighlighted(boolean value) { + super.setHighlighted(value); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + private Drawable getDrawableForCurrentState() { - return ResourceLoader.audioStatesDrawable[currentMessageObject.isOutOwner() ? buttonState : buttonState + 5][0]; - //buttonPressed ? 1 : + return ResourceLoader.audioStatesDrawable[currentMessageObject.isOutOwner() ? buttonState : buttonState + 5][isDrawSelectedBackground() ? 2 : (buttonPressed ? 1 : 0)]; } @Override @@ -377,13 +405,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega seekBar.draw(canvas); canvas.restore(); - if (currentMessageObject.isOutOwner()) { - timePaint.setColor(0xff70b15c); - circlePaint.setColor(0xff87bf78); - } else { - timePaint.setColor(0xffa1aab3); - circlePaint.setColor(0xff4195e5); - } + radialProgress.setProgressColor(currentMessageObject.isOutOwner() ? 0xff87bf78 : (isDrawSelectedBackground() ? 0xff83b2c2 : 0xffa2b5c7)); + timePaint.setColor(currentMessageObject.isOutOwner() ? 0xff70b15c : (isDrawSelectedBackground() ? 0xff89b4c1 : 0xffa1aab3)); + circlePaint.setColor(currentMessageObject.isOutOwner() ? 0xff87bf78 : 0xff4195e5); radialProgress.draw(canvas); canvas.save(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java index a7a0074e..4aceb766 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -3,12 +3,13 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -19,10 +20,13 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.text.Layout; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ClickableSpan; +import android.util.Log; import android.view.MotionEvent; import android.view.SoundEffectConstants; @@ -44,11 +48,13 @@ import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.TypefaceSpan; public class ChatBaseCell extends BaseCell implements MediaController.FileDownloadProgressListener { public interface ChatBaseCellDelegate { void didPressedUserAvatar(ChatBaseCell cell, TLRPC.User user); + void didPressedViaBot(ChatBaseCell cell, TLRPC.User user); void didPressedChannelAvatar(ChatBaseCell cell, TLRPC.Chat chat); void didPressedCancelSendButton(ChatBaseCell cell); void didLongPressed(ChatBaseCell cell); @@ -66,21 +72,21 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo protected static Paint urlPaint; private int TAG; - public boolean isChat = false; - protected boolean isPressed = false; - protected boolean forwardName = false; - protected boolean isHighlighted = false; - protected boolean media = false; + public boolean isChat; + protected boolean isPressed; + protected boolean forwardName; + protected boolean isHighlighted; + protected boolean media; protected boolean isCheckPressed = true; - private boolean wasLayout = false; - protected boolean isAvatarVisible = false; + private boolean wasLayout; + protected boolean isAvatarVisible; protected boolean drawBackground = true; - protected boolean allowAssistant = false; + protected boolean allowAssistant; protected MessageObject currentMessageObject; + private int viaWidth; + private int viaNameWidth; - private static TextPaint timePaintIn; - private static TextPaint timePaintOut; - private static TextPaint timeMediaPaint; + private static TextPaint timePaint; private static TextPaint namePaint; private static TextPaint forwardNamePaint; protected static TextPaint replyNamePaint; @@ -94,8 +100,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo private ImageReceiver avatarImage; private AvatarDrawable avatarDrawable; - private boolean avatarPressed = false; - private boolean forwardNamePressed = false; + private boolean avatarPressed; + private boolean forwardNamePressed; + private boolean forwardBotPressed; private StaticLayout replyNameLayout; private StaticLayout replyTextLayout; @@ -106,32 +113,33 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo private float replyNameOffset; protected int replyTextWidth; private float replyTextOffset; - private boolean needReplyImage = false; - private boolean replyPressed = false; + private boolean needReplyImage; + private boolean replyPressed; private TLRPC.FileLocation currentReplyPhoto; - private boolean drawShareButton; + //private boolean drawShareButton; + protected boolean drawShareButton; private boolean sharePressed; private int shareStartX; private int shareStartY; private StaticLayout nameLayout; protected int nameWidth; - private float nameOffsetX = 0; - protected boolean drawName = false; + private float nameOffsetX; + private float nameX; + protected boolean drawName; private StaticLayout forwardedNameLayout; protected int forwardedNameWidth; - protected boolean drawForwardedName = false; + protected boolean drawForwardedName; private int forwardNameX; private int forwardNameY; - private float forwardNameOffsetX = 0; + private float forwardNameOffsetX; private StaticLayout timeLayout; protected int timeWidth; private int timeTextWidth; private int timeX; - private TextPaint currentTimePaint; private String currentTimeString; protected boolean drawTime = true; @@ -145,6 +153,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo private String currentNameString; private TLRPC.User currentForwardUser; + private TLRPC.User currentViaBotUser; private TLRPC.Chat currentForwardChannel; private String currentForwardNameString; @@ -172,18 +181,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo public ChatBaseCell(Context context) { super(context); - if (timePaintIn == null) { - timePaintIn = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - timePaintIn.setTextSize(AndroidUtilities.dp(12)); - timePaintIn.setColor(0xffa1aab3); - - timePaintOut = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - timePaintOut.setTextSize(AndroidUtilities.dp(12)); - timePaintOut.setColor(0xff70b15c); - - timeMediaPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - timeMediaPaint.setTextSize(AndroidUtilities.dp(12)); - timeMediaPaint.setColor(0xffffffff); + if (timePaint == null) { + timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + timePaint.setTextSize(AndroidUtilities.dp(12)); namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); namePaint.setTextSize(AndroidUtilities.dp(15)); @@ -258,16 +258,18 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo int lBubbleColor = themePrefs.getInt("chatLBubbleColor", 0xffffffff); int lBubbleSColor = AndroidUtilities.setDarkColor(lBubbleColor, 0x15); - timePaintOut.setColor(themePrefs.getInt("chatRTimeColor", dColor)); - timePaintOut.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatTimeSize", 12))); - timePaintIn.setColor(themePrefs.getInt("chatLTimeColor", 0xffa1aab3)); - timePaintIn.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatTimeSize", 12))); + //timePaintOut.setColor(themePrefs.getInt("chatRTimeColor", dColor)); + //timePaintOut.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatTimeSize", 12))); + //timePaintIn.setColor(themePrefs.getInt("chatLTimeColor", 0xffa1aab3)); + //timePaintIn.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatTimeSize", 12))); int linkColor = themePrefs.getInt("chatLLinkColor", defColor); int bColor = AndroidUtilities.getIntAlphaColor("chatLBubbleColor", 0xffffffff, 0.9f); + int vColor = themePrefs.getInt("chatLTimeColor", 0xffa1aab3); if(currentMessageObject.isOut()){ bColor = AndroidUtilities.getIntAlphaColor("chatRBubbleColor", lColor, 0.9f); linkColor = themePrefs.getInt("chatRLinkColor", defColor); + vColor = themePrefs.getInt("chatRTimeColor", defColor); } replyTextPaint.linkColor = linkColor; @@ -290,6 +292,8 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo ResourceLoader.checkMediaDrawable.setColorFilter(checksColor, PorterDuff.Mode.MULTIPLY); ResourceLoader.halfCheckMediaDrawable.setColorFilter(checksColor, PorterDuff.Mode.MULTIPLY); ResourceLoader.halfCheckMediaDrawable.setColorFilter(checksColor, PorterDuff.Mode.MULTIPLY); + + ResourceLoader.viewsCountDrawable.setColorFilter(vColor, PorterDuff.Mode.SRC_IN); } catch (NullPointerException e) { FileLog.e("tmessages", e); } @@ -412,16 +416,19 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo return true; } + if (drawForwardedName) { newNameString = currentMessageObject.getForwardedName(); return currentForwardNameString == null && newNameString != null || currentForwardNameString != null && newNameString == null || currentForwardNameString != null && newNameString != null && !currentForwardNameString.equals(newNameString); } + return false; + } protected void measureTime(MessageObject messageObject) { currentTimeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); - timeTextWidth = timeWidth = (int) Math.ceil(timeMediaPaint.measureText(currentTimeString)); + timeTextWidth = timeWidth = (int) Math.ceil(timePaint.measureText(currentTimeString)); if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null)); - timeWidth += (int) Math.ceil(timeMediaPaint.measureText(currentViewsString)) + ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); + timeWidth += (int) Math.ceil(timePaint.measureText(currentViewsString)) + ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } } @@ -439,9 +446,12 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo replyTextLayout = null; replyNameWidth = 0; replyTextWidth = 0; + viaWidth = 0; + viaNameWidth = 0; currentReplyPhoto = null; currentUser = null; currentChat = null; + currentViaBotUser = null; if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { if (currentMessageObject.isContentUnread() && !currentMessageObject.isOut()) { @@ -453,14 +463,30 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } } + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + + //Log.e("chatBaseCell","messageObject.messageOwner.from_id " + messageObject.messageOwner.from_id); if (messageObject.messageOwner.from_id > 0) { currentUser = MessagesController.getInstance().getUser(messageObject.messageOwner.from_id); + if(currentUser != null && !currentMessageObject.isOut() && messageObject.type != 13){ + //Log.e("chatBaseCell"," chat_id " + messageObject.messageOwner.to_id.chat_id); + boolean showDSBtnUsers = preferences.getBoolean("showDSBtnUsers", false); + boolean showDSBtnGroups = preferences.getBoolean("showDSBtnGroups", true); + boolean showDSBtnSGroups = preferences.getBoolean("showDSBtnSGroups", true); + boolean showDSBtnBots = preferences.getBoolean("showDSBtnBots", true); + if(showDSBtnBots && currentUser.bot || !isChat && !currentUser.bot && showDSBtnUsers || showDSBtnSGroups && messageObject.isMegagroup() || messageObject.messageOwner.to_id.chat_id != 0 && showDSBtnGroups)drawShareButton = true; // Users Bots Supergroups + } } else if (messageObject.messageOwner.from_id < 0) { currentChat = MessagesController.getInstance().getChat(-messageObject.messageOwner.from_id); if (messageObject.messageOwner.to_id.channel_id != 0 && (messageObject.messageOwner.reply_to_msg_id == 0 || messageObject.type != 13)) { drawShareButton = true; } + if(!currentMessageObject.isOut() && messageObject.type != 13){ + boolean showDSBtnChannels = preferences.getBoolean("showDSBtnChannels", true); + drawShareButton = messageObject.messageOwner.to_id.channel_id != 0 && showDSBtnChannels; // Groups Channels + } } + setStatusColor(currentUser); //if (isChat && !messageObject.isOutOwner() && messageObject.messageOwner.from_id > 0) { if ( ((isChat || showAvatar) && !messageObject.isOutOwner() && messageObject.messageOwner.from_id > 0) @@ -489,27 +515,46 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, false); } - if (!media) { + /*if (!media) { if (currentMessageObject.isOutOwner()) { - currentTimePaint = timePaintOut; + //currentTimePaint = timePaintOut; } else { - currentTimePaint = timePaintIn; + //currentTimePaint = timePaintIn; } } else { - currentTimePaint = timeMediaPaint; - } + //currentTimePaint = timeMediaPaint; + }*/ currentTimeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); - timeTextWidth = timeWidth = (int)Math.ceil(currentTimePaint.measureText(currentTimeString)); + timeTextWidth = timeWidth = (int)Math.ceil(timePaint.measureText(currentTimeString)); if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null)); - viewsTextWidth = (int) Math.ceil(currentTimePaint.measureText(currentViewsString)); + viewsTextWidth = (int) Math.ceil(timePaint.measureText(currentViewsString)); timeWidth += viewsTextWidth + ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } namesOffset = 0; - if (drawName && isChat && !currentMessageObject.isOutOwner()) { + String viaUsername = null; + String viaString = null; + if (messageObject.messageOwner.via_bot_id != 0) { + TLRPC.User botUser = MessagesController.getInstance().getUser(messageObject.messageOwner.via_bot_id); + if (botUser != null && botUser.username != null && botUser.username.length() > 0) { + viaUsername = "@" + botUser.username; + viaString = " via " + viaUsername; + viaWidth = (int) Math.ceil(forwardNamePaint.measureText(viaString)); + currentViaBotUser = botUser; + } + } + boolean authorName = drawName && isChat && !currentMessageObject.isOutOwner(); + boolean viaBot = messageObject.messageOwner.fwd_from_id == null && currentViaBotUser != null; + if (authorName || viaBot) { + drawName = true; + nameWidth = getMaxNameWidth(); + if (nameWidth < 0) { + nameWidth = AndroidUtilities.dp(100); + } + if (authorName || !currentMessageObject.isOutOwner()) { if (currentUser != null) { currentNameString = UserObject.getUserName(currentUser); String currentUsernameString = currentUser.username; @@ -522,12 +567,41 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } else { currentNameString = "DELETED"; } - nameWidth = getMaxNameWidth(); - if (nameWidth < 0) { - nameWidth = AndroidUtilities.dp(100); + } else { + currentNameString = ""; } - CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace("\n", " "), namePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace("\n", " "), namePaint, nameWidth - AndroidUtilities.dp(12) - (viaBot ? viaWidth : 0), TextUtils.TruncateAt.END); + if (viaBot) { + viaNameWidth = (int) Math.ceil(namePaint.measureText(nameStringFinal, 0, nameStringFinal.length())); + if (viaNameWidth != 0) { + viaNameWidth += AndroidUtilities.dp(4); + } + SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int defColor = themePrefs.getInt("themeColor", AndroidUtilities.defColor); + int rColor = 0xff4a923c; + int lColor = 0xff006fc8; + if (currentMessageObject.isOutOwner()) { + rColor = themePrefs.getInt("chatForwardRColor", AndroidUtilities.setDarkColor(defColor, 0x15)); + }else{ + lColor = themePrefs.getInt("chatForwardLColor", defColor); + } + if (currentNameString.length() > 0) { + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format("%s via @%s", nameStringFinal, currentViaBotUser.username)); + //stringBuilder.setSpan(new TypefaceSpan(null, 0, currentMessageObject.isOutOwner() ? 0xff4a923c : 0xff006fc8), nameStringFinal.length() + 1, nameStringFinal.length() + 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new TypefaceSpan(null, 0, currentMessageObject.isOutOwner() ? rColor : lColor), nameStringFinal.length() + 1, nameStringFinal.length() + 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + //stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, currentMessageObject.isOutOwner() ? 0xff4a923c : 0xff006fc8), nameStringFinal.length() + 5, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, currentMessageObject.isOutOwner() ? rColor : lColor), nameStringFinal.length() + 5, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + nameStringFinal = stringBuilder; + } else { + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format("via @%s", currentViaBotUser.username)); + //stringBuilder.setSpan(new TypefaceSpan(null, 0, currentMessageObject.isOutOwner() ? 0xff4a923c : 0xff006fc8), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new TypefaceSpan(null, 0, currentMessageObject.isOutOwner() ? rColor : lColor), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + //stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, currentMessageObject.isOutOwner() ? 0xff4a923c : 0xff006fc8), 4, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, currentMessageObject.isOutOwner() ? rColor : lColor), 4, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + nameStringFinal = stringBuilder; + } + } try { nameLayout = new StaticLayout(nameStringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout != null && nameLayout.getLineCount() > 0) { @@ -563,9 +637,20 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } forwardedNameWidth = getMaxNameWidth(); - - CharSequence str = TextUtils.ellipsize(currentForwardNameString.replace("\n", " "), forwardNamePaint, forwardedNameWidth - AndroidUtilities.dp(40), TextUtils.TruncateAt.END); - str = AndroidUtilities.replaceTags(String.format("%s\n%s %s", LocaleController.getString("ForwardedMessage", R.string.ForwardedMessage), LocaleController.getString("From", R.string.From), str)); + /*SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int defColor = themePrefs.getInt("themeColor", AndroidUtilities.defColor); + if (currentMessageObject.isOutOwner()) { + forwardNamePaint.setColor(themePrefs.getInt("chatForwardRColor", AndroidUtilities.setDarkColor(defColor, 0x15))); + }else{ + forwardNamePaint.setColor(themePrefs.getInt("chatForwardLColor", defColor)); + }*/ + CharSequence str = TextUtils.ellipsize(currentForwardNameString.replace("\n", " "), forwardNamePaint, forwardedNameWidth - AndroidUtilities.dp(40) - viaWidth, TextUtils.TruncateAt.END); + if (viaString != null) { + viaNameWidth = (int) Math.ceil(forwardNamePaint.measureText(LocaleController.getString("From", R.string.From) + " " + str)); + str = AndroidUtilities.replaceTags(String.format("%s\n%s %s via %s", LocaleController.getString("ForwardedMessage", R.string.ForwardedMessage), LocaleController.getString("From", R.string.From), str, viaUsername)); + } else { + str = AndroidUtilities.replaceTags(String.format("%s\n%s %s", LocaleController.getString("ForwardedMessage", R.string.ForwardedMessage), LocaleController.getString("From", R.string.From), str)); + } forwardedNameLayout = StaticLayoutEx.createStaticLayout(str, forwardNamePaint, forwardedNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, forwardedNameWidth, 2); if (forwardedNameLayout.getLineCount() > 1) { forwardedNameWidth = Math.max((int) Math.ceil(forwardedNameLayout.getLineWidth(0)), (int) Math.ceil(forwardedNameLayout.getLineWidth(1))); @@ -715,7 +800,14 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo avatarPressed = true; result = true; } else if (drawForwardedName && forwardedNameLayout != null && x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + AndroidUtilities.dp(32)) { + if (viaWidth != 0 && x >= forwardNameX + viaNameWidth + AndroidUtilities.dp(4)) { + forwardBotPressed = true; + } else { forwardNamePressed = true; + } + result = true; + } else if (drawName && nameLayout != null && viaWidth != 0 && x >= nameX + viaNameWidth && x <= nameX + viaNameWidth + viaWidth && y >= AndroidUtilities.dp(6) && y <= AndroidUtilities.dp(30)) { + forwardBotPressed = true; result = true; } else if (currentMessageObject.isReply() && x >= replyStartX && x <= replyStartX + Math.max(replyNameWidth, replyTextWidth) && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35)) { replyPressed = true; @@ -769,6 +861,26 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo forwardNamePressed = false; } } + } else if (forwardBotPressed) { + if (event.getAction() == MotionEvent.ACTION_UP) { + forwardBotPressed = false; + playSoundEffect(SoundEffectConstants.CLICK); + if (delegate != null) { + delegate.didPressedViaBot(this, currentViaBotUser); + } + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + forwardBotPressed = false; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (drawForwardedName && forwardedNameLayout != null) { + if (!(x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + AndroidUtilities.dp(32))) { + forwardBotPressed = false; + } + } else { + if (!(x >= nameX + viaNameWidth && x <= nameX + viaNameWidth + viaWidth && y >= AndroidUtilities.dp(6) && y <= AndroidUtilities.dp(30))) { + forwardBotPressed = false; + } + } + } } else if (replyPressed) { if (event.getAction() == MotionEvent.ACTION_UP) { replyPressed = false; @@ -815,7 +927,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo layoutWidth = getMeasuredWidth(); layoutHeight = getMeasuredHeight(); - timeLayout = new StaticLayout(currentTimeString, currentTimePaint, timeTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + timeLayout = new StaticLayout(currentTimeString, timePaint, timeTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (!media) { if (!currentMessageObject.isOutOwner()) { //timeX = backgroundWidth - AndroidUtilities.dp(9) - timeWidth + (isChat && currentMessageObject.messageOwner.from_id > 0 ? AndroidUtilities.dp(52) : 0); @@ -837,7 +949,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - viewsLayout = new StaticLayout(currentViewsString, currentTimePaint, viewsTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + viewsLayout = new StaticLayout(currentViewsString, timePaint, viewsTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else { viewsLayout = null; } @@ -871,6 +983,10 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } } + protected boolean isDrawSelectedBackground() { + return isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted; + } + @Override protected void onDraw(Canvas canvas) { if (currentMessageObject == null) { @@ -889,10 +1005,23 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo statusBG.draw(canvas); } } + + //if (media) { + // timePaint.setColor(0xffffffff); + //} else { + if (currentMessageObject.isOutOwner()) { + //timePaint.setColor(0xff70b15c); + timePaint.setColor(themePrefs.getInt("chatRTimeColor", AndroidUtilities.setDarkColor(themePrefs.getInt("themeColor", AndroidUtilities.defColor), 0x15))); + } else { + //timePaint.setColor(isDrawSelectedBackground() ? 0xff89b4c1 : 0xffa1aab3); + timePaint.setColor(isDrawSelectedBackground() ? 0xff89b4c1 : themePrefs.getInt("chatLTimeColor", 0xffa1aab3)); + } + //} + updateTheme(); Drawable currentBackgroundDrawable; if (currentMessageObject.isOutOwner()) { - if (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) { + if (isDrawSelectedBackground()) { if (!media) { currentBackgroundDrawable = ResourceLoader.backgroundDrawableOutSelected; } else { @@ -909,11 +1038,11 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo if ((showMyAvatar && !isChat) || (showMyAvatarGroup && isChat)) { setDrawableBounds(currentBackgroundDrawable, layoutWidth - backgroundWidth - (!media ? 0 : AndroidUtilities.dp(9)) - AndroidUtilities.dp(leftBound), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); }else{ - setDrawableBounds(currentBackgroundDrawable, layoutWidth - backgroundWidth - (!media ? 0 : AndroidUtilities.dp(9)), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); + setDrawableBounds(currentBackgroundDrawable, layoutWidth - backgroundWidth - (!media ? 0 : AndroidUtilities.dp(9)), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); } } else { - if (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) { + if (isDrawSelectedBackground()) { if (!media) { currentBackgroundDrawable = ResourceLoader.backgroundDrawableInSelected; } else { @@ -927,8 +1056,10 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } } if ((isChat || showAvatar) && currentMessageObject.messageOwner.from_id > 0) { + //Log.e("chatBaseCell","1 backgroundWidth: " + backgroundWidth); setDrawableBounds(currentBackgroundDrawable, AndroidUtilities.dp(leftBound + (!media ? 0 : 9)), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); } else { + //Log.e("chatBaseCell","2 backgroundWidth: " + backgroundWidth); setDrawableBounds(currentBackgroundDrawable, (!media ? 0 : AndroidUtilities.dp(9)), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); } } @@ -939,7 +1070,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo onAfterBackgroundDraw(canvas); if (drawShareButton) { - ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].setBounds(shareStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8), shareStartY = layoutHeight - AndroidUtilities.dp(41), currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(40), layoutHeight - AndroidUtilities.dp(9)); + //ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].setBounds(shareStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8), shareStartY = layoutHeight - AndroidUtilities.dp(41), currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(40), layoutHeight - AndroidUtilities.dp(9)); + //boolean b = currentMessageObject.messageOwner.from_id < 0 && (currentMessageObject.messageOwner.to_id.channel_id != 0 && (currentMessageObject.messageOwner.reply_to_msg_id == 0 || currentMessageObject.type != 13)); + ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].setBounds(shareStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(1), shareStartY = layoutHeight - AndroidUtilities.dp(35), currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(33), layoutHeight - AndroidUtilities.dp(3)); ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].draw(canvas); } @@ -948,10 +1081,10 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo int mColor = themePrefs.getInt("chatMemberColor", AndroidUtilities.getIntDarkerColor("themeColor", 0x15)); if (drawName && nameLayout != null) { canvas.save(); - if (media) { - canvas.translate(currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(10) - nameOffsetX, AndroidUtilities.dp(10)); + if (media || currentMessageObject.isOutOwner()) { + canvas.translate(nameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(10) - nameOffsetX, AndroidUtilities.dp(10)); } else { - canvas.translate(currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19) - nameOffsetX, AndroidUtilities.dp(10)); + canvas.translate(nameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19) - nameOffsetX, AndroidUtilities.dp(10)); } if (currentUser != null) { if(mCheck){ @@ -974,6 +1107,10 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } nameLayout.draw(canvas); canvas.restore(); + + /*if (forwardedNameLayout == null && viaWidth != 0) { + canvas.drawRect(nameX + viaNameWidth, AndroidUtilities.dp(6), nameX + viaNameWidth + viaWidth, AndroidUtilities.dp(30), namePaint); + }*/ } if (drawForwardedName && forwardedNameLayout != null) { @@ -983,7 +1120,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo //forwardNamePaint.setColor(0xff4a923c); forwardNamePaint.setColor(themePrefs.getInt("chatForwardRColor", AndroidUtilities.setDarkColor(defColor, 0x15))); forwardNameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(10); - if((showMyAvatar && !isChat) || (showMyAvatarGroup && isChat))forwardNameY = AndroidUtilities.dp((drawName ? 10 : 0)); + if(showMyAvatarGroup && isChat)forwardNameY = AndroidUtilities.dp(10); + //if((showMyAvatar && !isChat) || (showMyAvatarGroup && isChat))forwardNameY = AndroidUtilities.dp((drawName ? 10 : 0)); + if(!isChat && showMyAvatar)forwardNameY = AndroidUtilities.dp(10); } else { //forwardNamePaint.setColor(0xff006fc8); forwardNamePaint.setColor(themePrefs.getInt("chatForwardLColor", defColor)); @@ -992,12 +1131,16 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } else { forwardNameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19); } - if((!isChat && showAvatar))forwardNameY = AndroidUtilities.dp((drawName ? 10 : 0)); + if(!isChat && showAvatar)forwardNameY = AndroidUtilities.dp(10); } canvas.save(); canvas.translate(forwardNameX - forwardNameOffsetX, forwardNameY); forwardedNameLayout.draw(canvas); canvas.restore(); + + /*if (viaWidth != 0) { + canvas.drawRect(forwardNameX + viaNameWidth, forwardNameY, forwardNameX + viaNameWidth + viaWidth, forwardNameY + AndroidUtilities.dp(32), namePaint); + }*/ } if (currentMessageObject.isReply()) { @@ -1102,12 +1245,13 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo ResourceLoader.errorDrawable.draw(canvas); } } else { - setDrawableBounds(ResourceLoader.viewsMediaCountDrawable, timeX, layoutHeight - AndroidUtilities.dp(10) - timeLayout.getHeight()); - ResourceLoader.viewsMediaCountDrawable.draw(canvas); + Drawable countDrawable = ResourceLoader.viewsMediaCountDrawable[isDrawSelectedBackground() ? 1 : 0]; + setDrawableBounds(countDrawable, timeX, layoutHeight - AndroidUtilities.dp(10) - timeLayout.getHeight()); + countDrawable.draw(canvas); if (viewsLayout != null) { canvas.save(); - canvas.translate(timeX + ResourceLoader.viewsMediaCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(12.0f) - timeLayout.getHeight()); + canvas.translate(timeX + countDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(12.0f) - timeLayout.getHeight()); viewsLayout.draw(canvas); canvas.restore(); } @@ -1125,8 +1269,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo if (currentMessageObject.isSending()) { if (!currentMessageObject.isOutOwner()) { - setDrawableBounds(ResourceLoader.clockChannelDrawable, timeX + AndroidUtilities.dp(11), layoutHeight - AndroidUtilities.dp(8.5f) - ResourceLoader.clockChannelDrawable.getIntrinsicHeight()); - ResourceLoader.clockChannelDrawable.draw(canvas); + Drawable clockDrawable = ResourceLoader.clockChannelDrawable[isDrawSelectedBackground() ? 1 : 0]; + setDrawableBounds(clockDrawable, timeX + AndroidUtilities.dp(11), layoutHeight - AndroidUtilities.dp(8.5f) - clockDrawable.getIntrinsicHeight()); + clockDrawable.draw(canvas); } } else if (currentMessageObject.isSendError()) { if (!currentMessageObject.isOutOwner()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java index 27bf36de..ba243273 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java index a54eb8a1..b7cec741 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -23,6 +23,7 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ClickableSpan; +import android.util.Log; import android.view.MotionEvent; import android.view.SoundEffectConstants; @@ -42,7 +43,6 @@ import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AvatarDrawable; -import org.telegram.ui.Components.GifDrawable; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.StaticLayoutEx; @@ -50,6 +50,7 @@ import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.PhotoViewer; import java.io.File; +import java.util.HashMap; import java.util.Locale; public class ChatMediaCell extends ChatBaseCell { @@ -59,14 +60,12 @@ public class ChatMediaCell extends ChatBaseCell { } private static TextPaint infoPaint; - private static MessageObject lastDownloadedGifMessage = null; private static TextPaint namePaint; private static Paint docBackPaint; private static Paint deleteProgressPaint; private static TextPaint locationTitlePaint; private static TextPaint locationAddressPaint; - private GifDrawable gifDrawable = null; private RadialProgress radialProgress; private int photoWidth; @@ -111,6 +110,8 @@ public class ChatMediaCell extends ChatBaseCell { private int captionY; private int captionHeight; + private long docSize; + public ChatMediaCell(Context context) { super(context); @@ -144,15 +145,6 @@ public class ChatMediaCell extends ChatBaseCell { radialProgress = new RadialProgress(this); } - public void clearGifImage() { - if (currentMessageObject != null && currentMessageObject.type == 8) { - gifDrawable = null; - buttonState = 2; - radialProgress.setBackground(getDrawableForCurrentState(), false, false); - invalidate(); - } - } - public void setMediaDelegate(ChatMediaCellDelegate delegate) { this.mediaDelegate = delegate; } @@ -161,10 +153,6 @@ public class ChatMediaCell extends ChatBaseCell { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); photoImage.onDetachedFromWindow(); - if (gifDrawable != null) { - MediaController.getInstance().clearGifDrawable(this); - gifDrawable = null; - } MediaController.getInstance().removeLoadingFileObserver(this); } @@ -274,6 +262,12 @@ public class ChatMediaCell extends ChatBaseCell { } if (imagePressed && currentMessageObject.isSecretPhoto()) { imagePressed = false; + } else if (imagePressed && currentMessageObject.isSendError()) { + imagePressed = false; + result = false; + } else if (imagePressed && currentMessageObject.type == 8 && buttonState == -1 && MediaController.getInstance().canAutoplayGifs()) { + imagePressed = false; + result = false; } else if (result) { startCheckLongPress(); } @@ -358,9 +352,9 @@ public class ChatMediaCell extends ChatBaseCell { } else if (currentMessageObject.type == 8) { if (buttonState == -1) { buttonState = 2; - if (gifDrawable != null) { - gifDrawable.pause(); - } + currentMessageObject.audioProgress = 1; + photoImage.setAllowStartAnimation(false); + photoImage.stopAnimation(); radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } else if (buttonState == 2 || buttonState == 0) { @@ -383,13 +377,37 @@ public class ChatMediaCell extends ChatBaseCell { } } + @Override + public void setCheckPressed(boolean value, boolean pressed) { + super.setCheckPressed(value, pressed); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + + @Override + public void setHighlighted(boolean value) { + super.setHighlighted(value); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + if (radialProgress.swapBackground(getDrawableForCurrentState())) { + invalidate(); + } + } + private Drawable getDrawableForCurrentState() { if (buttonState >= 0 && buttonState < 4) { - if (currentMessageObject.type == 9 && gifDrawable == null) { + if (currentMessageObject.type == 9) { if (buttonState == 1 && !currentMessageObject.isSending()) { - return ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOutOwner() ? 1 : 0]; + return ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOutOwner() ? 1 : (isDrawSelectedBackground() ? 2 : 0)]; } else { - return ResourceLoader.buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOutOwner() ? 1 : 0]; + return ResourceLoader.buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOutOwner() ? 1 : (isDrawSelectedBackground() ? 2 : 0)]; } } else { if (buttonState == 1 && !currentMessageObject.isSending()) { @@ -399,8 +417,8 @@ public class ChatMediaCell extends ChatBaseCell { } } } else if (buttonState == -1) { - if (currentMessageObject.type == 9 && gifDrawable == null) { - return currentMessageObject.isOutOwner() ? ResourceLoader.placeholderDocOutDrawable : ResourceLoader.placeholderDocInDrawable; + if (currentMessageObject.type == 9) { + return ResourceLoader.placeholderDocDrawable[currentMessageObject.isOutOwner() ? 1 : (isDrawSelectedBackground() ? 2 : 0)]; } } return null; @@ -412,9 +430,11 @@ public class ChatMediaCell extends ChatBaseCell { radialProgress.setProgress(0, false); if (currentMessageObject.type == 1) { photoImage.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilter, currentPhotoObject.size, null, false); - } else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) { - FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false); - lastDownloadedGifMessage = currentMessageObject; + } else if (currentMessageObject.type == 8) { + currentMessageObject.audioProgress = 2; + photoImage.setImage(currentMessageObject.messageOwner.media.document, null, currentPhotoObject != null ? currentPhotoObject.location : null, currentPhotoFilter, currentMessageObject.messageOwner.media.document.size, null, false); + } else if (currentMessageObject.type == 9) { + FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, false, false); } else if (currentMessageObject.type == 3) { FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video, true); } @@ -428,13 +448,10 @@ public class ChatMediaCell extends ChatBaseCell { } } else { cancelLoading = true; - if (currentMessageObject.type == 1) { + if (currentMessageObject.type == 1 || currentMessageObject.type == 8) { photoImage.cancelLoadImage(); - } else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) { + } else if (currentMessageObject.type == 9) { FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.document); - if (lastDownloadedGifMessage != null && lastDownloadedGifMessage.getId() == currentMessageObject.getId()) { - lastDownloadedGifMessage = null; - } } else if (currentMessageObject.type == 3) { FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.video); } @@ -443,15 +460,11 @@ public class ChatMediaCell extends ChatBaseCell { invalidate(); } } else if (buttonState == 2) { - if (gifDrawable == null) { - gifDrawable = MediaController.getInstance().getGifDrawable(this, true); - } - if (gifDrawable != null) { - gifDrawable.start(); - gifDrawable.invalidateSelf(); - buttonState = -1; - radialProgress.setBackground(getDrawableForCurrentState(), false, animated); - } + photoImage.setAllowStartAnimation(true); + photoImage.startAnimation(); + currentMessageObject.audioProgress = 0; + buttonState = -1; + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); } else if (buttonState == 3) { if (delegate != null) { delegate.didClickedImage(this); @@ -508,21 +521,26 @@ public class ChatMediaCell extends ChatBaseCell { @Override public void setMessageObject(MessageObject messageObject) { + boolean messageChanged = currentMessageObject != messageObject; boolean dataChanged = currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet); if (currentMessageObject != messageObject || isPhotoDataChanged(messageObject) || dataChanged) { - drawForwardedName = (messageObject.type == 3 || messageObject.type == 1) && messageObject.messageOwner.fwd_from_id != null && messageObject.messageOwner.fwd_from_id.channel_id != 0; + drawForwardedName = messageObject.messageOwner.fwd_from_id != null && messageObject.type != 13; media = messageObject.type != 9; cancelLoading = false; additionHeight = 0; resetPressedLink(); + if (messageObject.audioProgress != 2 && !MediaController.getInstance().canAutoplayGifs() && messageObject.type == 8) { + messageObject.audioProgress = 1; + } buttonState = -1; - gifDrawable = null; currentPhotoObject = null; currentPhotoObjectThumb = null; currentUrl = null; photoNotSet = false; drawBackground = true; + drawName = false; + photoImage.setAllowStartAnimation(messageObject.audioProgress == 0); photoImage.setForcePreview(messageObject.isSecretPhoto()); if (messageObject.type == 9) { @@ -534,7 +552,9 @@ public class ChatMediaCell extends ChatBaseCell { if (AndroidUtilities.isTablet()) { maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(122 + 86 + 24); } else { - maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122 + 86 + 24); + //maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122 + 86 + 24); + maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp((isChat && messageObject.messageOwner.from_id < 0 ? 15 : leftBound) + 70 + 86 + 24); + if(!messageObject.isOutOwner() && (!isChat && showAvatar || isChat && messageObject.messageOwner.from_id > 0))maxWidth = maxWidth - AndroidUtilities.dp(15); } if (currentNameString == null || !currentNameString.equals(name)) { currentNameString = name; @@ -546,13 +566,11 @@ public class ChatMediaCell extends ChatBaseCell { } else { nameWidth = maxWidth; } - //nameWidth = Math.min(maxWidth, (int) Math.ceil(namePaint.measureText(currentNameString))); - //CharSequence str = TextUtils.ellipsize(currentNameString, namePaint, nameWidth, TextUtils.TruncateAt.END); - //nameLayout = new StaticLayout(str, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size) + " " + messageObject.getExtension(); + radialProgress.setSizeAndType(messageObject.messageOwner.media.document.size, messageObject.type); //plus if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; infoOffset = 0; @@ -572,9 +590,8 @@ public class ChatMediaCell extends ChatBaseCell { infoLayout = new StaticLayout(str2, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } } else if (messageObject.type == 8) { - gifDrawable = MediaController.getInstance().getGifDrawable(this, false); - String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size); + radialProgress.setSizeAndType(messageObject.messageOwner.media.document.size, messageObject.type); //plus if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; infoOffset = 0; @@ -583,30 +600,28 @@ public class ChatMediaCell extends ChatBaseCell { } nameLayout = null; currentNameString = null; - } else if (messageObject.type == 3) { + } else if (messageObject.type == 3) { //VIDEO int duration = messageObject.messageOwner.media.video.duration; int minutes = duration / 60; int seconds = duration - minutes * 60; String str = String.format("%d:%02d, %s", minutes, seconds, AndroidUtilities.formatFileSize(messageObject.messageOwner.media.video.size)); + radialProgress.setSizeAndType(messageObject.messageOwner.media.video.size, messageObject.type); //plus if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; - //infoOffset = ResourceLoader.videoIconDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4); - //infoWidth = (int) Math.ceil(infoPaint.measureText(currentInfoString)); - //infoLayout = new StaticLayout(currentInfoString, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + infoOffset = ResourceLoader.videoIconDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4); + infoWidth = (int) Math.ceil(infoPaint.measureText(currentInfoString)); + infoLayout = new StaticLayout(currentInfoString, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); //Plus - infoLayout = null; + //infoLayout = null; infoLayout2 = null; if(isChat){ infoOffset2 = ResourceLoader.videoIconDrawable.getIntrinsicWidth() + AndroidUtilities.dp(5); infoOffset = 0; - String senderName = getCurrentNameString(messageObject); - infoWidth2 = (int) Math.ceil(infoPaint.measureText(currentInfoString)); //infoWidth = (int) Math.ceil(senderPaint.measureText(senderName)); infoWidth = Math.max(infoWidth2, (int) Math.ceil(senderPaint.measureText(senderName))); infoLayout = new StaticLayout(senderName, senderPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - infoLayout2 = new StaticLayout(currentInfoString, infoPaint, infoWidth2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); }// @@ -615,7 +630,7 @@ public class ChatMediaCell extends ChatBaseCell { currentNameString = null; }//Plus: member name in photos else if (messageObject.type == 1) { //PHOTO - + radialProgress.setSizeAndType(0, messageObject.type); currentNameString = getCurrentNameString(messageObject); String senderName = currentNameString; @@ -624,8 +639,9 @@ public class ChatMediaCell extends ChatBaseCell { currentInfoString = senderName; infoOffset = 0; infoLayout = null; + //Log.e("chatMediaCell"," chat_id " + messageObject.messageOwner.to_id.chat_id + " channel_id " + messageObject.messageOwner.to_id.channel_id + " from_id " + messageObject.messageOwner.from_id); try{ - if(isChat){ + if(isChat && messageObject.messageOwner.from_id > 0){ infoWidth = (int) Math.min(Math.ceil(namePaint.measureText(currentNameString)), Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f); CharSequence str = TextUtils.ellipsize(currentNameString, senderPaint, infoWidth, TextUtils.TruncateAt.END); infoLayout = new StaticLayout(str, senderPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); @@ -650,6 +666,8 @@ public class ChatMediaCell extends ChatBaseCell { photoWidth = AndroidUtilities.dp(86); photoHeight = AndroidUtilities.dp(86); backgroundWidth = photoWidth + Math.max(nameWidth, infoWidth) + AndroidUtilities.dp(68); + //Log.e("ChatMediaCell","backgroundWidth " + backgroundWidth + " nameWidth " + nameWidth + " infoWidth " + infoWidth + " drawShareButton " + drawShareButton); + //backgroundWidth = backgroundWidth - AndroidUtilities.dp(5); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); photoImage.setNeedsQualityThumb(true); photoImage.setShouldGenerateQualityThumb(true); @@ -703,7 +721,8 @@ public class ChatMediaCell extends ChatBaseCell { photoImage.setImage(currentUrl, null, messageObject.isOutOwner() ? ResourceLoader.geoOutDrawable : ResourceLoader.geoInDrawable, null, 0); } else if (messageObject.type == 13) { //webp drawBackground = false; - for (TLRPC.DocumentAttribute attribute : messageObject.messageOwner.media.document.attributes) { + for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { photoWidth = attribute.w; photoHeight = attribute.h; @@ -752,12 +771,15 @@ public class ChatMediaCell extends ChatBaseCell { "b1", messageObject.messageOwner.media.document.size, "webp", true); } + radialProgress.setSizeAndType(messageObject.messageOwner.media.document.size, messageObject.type); //plus } else { if (AndroidUtilities.isTablet()) { photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); } else { - photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); + //photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); + photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.68f); } + //Log.e("ChatMediaCell","photoWidth 1 "+photoWidth + " drawShareButton " + drawShareButton); photoHeight = photoWidth + AndroidUtilities.dp(100); if (photoWidth > AndroidUtilities.getPhotoSize()) { @@ -766,7 +788,7 @@ public class ChatMediaCell extends ChatBaseCell { if (photoHeight > AndroidUtilities.getPhotoSize()) { photoHeight = AndroidUtilities.getPhotoSize(); } - + //Log.e("ChatMediaCell","photoWidth 2 "+photoWidth); if (messageObject.type == 1) { photoImage.setNeedsQualityThumb(false); photoImage.setShouldGenerateQualityThumb(false); @@ -789,15 +811,14 @@ public class ChatMediaCell extends ChatBaseCell { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - int w = AndroidUtilities.dp(100); - int h = AndroidUtilities.dp(100); + int w = 0; + int h = 0; - - if (currentPhotoObject != null) { - if (currentPhotoObject == currentPhotoObjectThumb) { + if (currentPhotoObject != null && currentPhotoObject == currentPhotoObjectThumb) { currentPhotoObjectThumb = null; } + if (currentPhotoObject != null) { float scale = (float) currentPhotoObject.w / (float) photoWidth; w = (int) (currentPhotoObject.w / scale); h = (int) (currentPhotoObject.h / scale); @@ -825,6 +846,35 @@ public class ChatMediaCell extends ChatBaseCell { } } + if ((w == 0 || h == 0) && messageObject.type == 8) { + for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + float scale = (float) attribute.w / (float) photoWidth; + w = (int) (attribute.w / scale); + h = (int) (attribute.h / scale); + if (h > photoHeight) { + float scale2 = h; + h = photoHeight; + scale2 /= h; + w = (int) (w / scale2); + } else if (h < AndroidUtilities.dp(120)) { + h = AndroidUtilities.dp(120); + float hScale = (float) attribute.h / h; + if (attribute.w / hScale < photoWidth) { + w = (int) (attribute.w / hScale); + } + } + break; + } + } + } + + + if (w == 0 || h == 0) { + w = h = AndroidUtilities.dp(100); + } + measureTime(messageObject); int timeWidthTotal = timeWidth + AndroidUtilities.dp(14 + (messageObject.isOutOwner() ? 20 : 0)); if (w < timeWidthTotal) { @@ -854,20 +904,20 @@ public class ChatMediaCell extends ChatBaseCell { } nameLayout = new StaticLayout(messageObject.caption, MessageObject.textPaint, photoWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout != null && nameLayout.getLineCount() > 0) { - captionHeight = nameLayout.getHeight(); - additionHeight += captionHeight + AndroidUtilities.dp(9); - float lastLineWidth = nameLayout.getLineWidth(nameLayout.getLineCount() - 1) + nameLayout.getLineLeft(nameLayout.getLineCount() - 1); - if (photoWidth - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) { - additionHeight += AndroidUtilities.dp(14); + captionHeight = nameLayout.getHeight(); + additionHeight += captionHeight + AndroidUtilities.dp(9); + float lastLineWidth = nameLayout.getLineWidth(nameLayout.getLineCount() - 1) + nameLayout.getLineLeft(nameLayout.getLineCount() - 1); + if (photoWidth - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) { + additionHeight += AndroidUtilities.dp(14); + } } - } } catch (Exception e) { FileLog.e("tmessages", e); } } - + //Log.e("ChatMediaCell","backgroundWidth: " + backgroundWidth); currentPhotoFilter = String.format(Locale.US, "%d_%d", (int) (w / AndroidUtilities.density), (int) (h / AndroidUtilities.density)); - if (messageObject.photoThumbs.size() > 1 || messageObject.type == 3 || messageObject.type == 8) { + if (messageObject.photoThumbs != null && messageObject.photoThumbs.size() > 1 || messageObject.type == 3 || messageObject.type == 8) { if (messageObject.isSecretPhoto()) { currentPhotoFilter += "_b2"; } else { @@ -875,17 +925,17 @@ public class ChatMediaCell extends ChatBaseCell { } } - if (currentPhotoObject != null) { boolean noSize = false; if (messageObject.type == 3 || messageObject.type == 8) { noSize = true; } - if (!noSize && currentPhotoObject.size == 0) { + if (currentPhotoObject != null && !noSize && currentPhotoObject.size == 0) { currentPhotoObject.size = -1; } - String fileName = FileLoader.getAttachFileName(currentPhotoObject); if (messageObject.type == 1) { + if (currentPhotoObject != null) { + String fileName = FileLoader.getAttachFileName(currentPhotoObject); boolean photoExist = true; File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); if (!cacheFile.exists()) { @@ -912,16 +962,48 @@ public class ChatMediaCell extends ChatBaseCell { } } } else { - photoImage.setImage(null, null, currentPhotoObject.location, currentPhotoFilter, 0, null, false); - } - } else { photoImage.setImageBitmap((Bitmap) null); } + } else if (messageObject.type == 8) { + String fileName = FileLoader.getAttachFileName(messageObject.messageOwner.media.document); + File cacheFile = null; + boolean localFile = false; + if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() != 0) { + cacheFile = new File(messageObject.messageOwner.attachPath); + if (!cacheFile.exists()) { + cacheFile = null; + } else { + MediaController.getInstance().removeLoadingFileObserver(this); + localFile = true; + } + } + if (cacheFile == null) { + cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); + if (!cacheFile.exists()) { + cacheFile = null; + } + } + if (!messageObject.isSending() && (cacheFile != null || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_GIF) && MessageObject.isNewGifDocument(messageObject.messageOwner.media.document) || FileLoader.getInstance().isLoadingFile(fileName))) { + if (localFile) { + photoImage.setImage(null, messageObject.isSendError() ? null : cacheFile.getAbsolutePath(), null, null, currentPhotoObject != null ? currentPhotoObject.location : null, currentPhotoFilter, 0, null, false); + } else { + photoImage.setImage(messageObject.messageOwner.media.document, null, currentPhotoObject != null ? currentPhotoObject.location : null, currentPhotoFilter, messageObject.messageOwner.media.document.size, null, false); + } + } else { + photoNotSet = true; + photoImage.setImage(null, null, currentPhotoObject != null ? currentPhotoObject.location : null, currentPhotoFilter, 0, null, false); + } + } else { + photoImage.setImage(null, null, currentPhotoObject != null ? currentPhotoObject.location : null, currentPhotoFilter, 0, null, false); + } } + super.setMessageObject(messageObject); if (drawForwardedName) { namesOffset += AndroidUtilities.dp(5); + } else if (drawName && messageObject.messageOwner.reply_to_msg_id == 0) { + namesOffset += AndroidUtilities.dp(7); } invalidate(); @@ -947,7 +1029,7 @@ public class ChatMediaCell extends ChatBaseCell { return; } //fileName = FileLoader.getAttachFileName(currentPhotoObject); - fileName = FileLoader.getAttachFileName(currentPhotoObject, currentMessageObject.isOutOwner()); + fileName = FileLoader.getAttachFileName(currentPhotoObject, null, currentMessageObject.isOutOwner()); cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); } else if (currentMessageObject.type == 8 || currentMessageObject.type == 3 || currentMessageObject.type == 9) { if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() != 0) { @@ -958,24 +1040,37 @@ public class ChatMediaCell extends ChatBaseCell { } } if (fileName == null) { + if (!currentMessageObject.isSendError()) { fileName = currentMessageObject.getFileName(); cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); } } - if (fileName == null) { + } + if (fileName == null || fileName.length() == 0) { radialProgress.setBackground(null, false, false); return; } if (currentMessageObject.isOut() && currentMessageObject.isSending()) { if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) { MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this); - buttonState = 1; - radialProgress.setBackground(getDrawableForCurrentState(), true, animated); + boolean needProgress = currentMessageObject.messageOwner.attachPath == null || !currentMessageObject.messageOwner.attachPath.startsWith("http"); + HashMap params = currentMessageObject.messageOwner.params; + if (currentMessageObject.messageOwner.message != null && params != null && (params.containsKey("url") || params.containsKey("bot"))) { + needProgress = false; + buttonState = -1; + } else { + buttonState = 1; + } + radialProgress.setBackground(getDrawableForCurrentState(), needProgress, animated); + if (needProgress) { Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath); if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) { progress = 1.0f; } radialProgress.setProgress(progress != null ? progress : 0, false); + } else { + radialProgress.setProgress(0, false); + } invalidate(); } } else { @@ -990,11 +1085,13 @@ public class ChatMediaCell extends ChatBaseCell { float setProgress = 0; boolean progressVisible = false; if (!FileLoader.getInstance().isLoadingFile(fileName)) { - if (cancelLoading || currentMessageObject.type != 1 || !MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { - buttonState = 0; - } else { + if (!cancelLoading && + (currentMessageObject.type == 1 && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO) || + currentMessageObject.type == 8 && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_GIF) && MessageObject.isNewGifDocument(currentMessageObject.messageOwner.media.document)) ) { progressVisible = true; buttonState = 1; + } else { + buttonState = 0; } } else { progressVisible = true; @@ -1007,7 +1104,7 @@ public class ChatMediaCell extends ChatBaseCell { invalidate(); } else { MediaController.getInstance().removeLoadingFileObserver(this); - if (currentMessageObject.type == 8 && (gifDrawable == null || !gifDrawable.isRunning())) { + if (currentMessageObject.type == 8 && !photoImage.isAllowStartAnimation()) { buttonState = 2; } else if (currentMessageObject.type == 3) { buttonState = 3; @@ -1015,6 +1112,9 @@ public class ChatMediaCell extends ChatBaseCell { buttonState = -1; } radialProgress.setBackground(getDrawableForCurrentState(), false, animated); + if (photoNotSet) { + setMessageObject(currentMessageObject); + } invalidate(); } } @@ -1090,19 +1190,10 @@ public class ChatMediaCell extends ChatBaseCell { @Override protected void onAfterBackgroundDraw(Canvas canvas) { - boolean imageDrawn = false; - if (gifDrawable != null) { - drawTime = !gifDrawable.isPlaying(); - canvas.save(); - gifDrawable.setBounds(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX() + photoWidth, photoImage.getImageY() + photoHeight); - gifDrawable.draw(canvas); - canvas.restore(); - } else { - photoImage.setPressed(isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted); + photoImage.setPressed(isDrawSelectedBackground()); photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false); - imageDrawn = photoImage.draw(canvas); + boolean imageDrawn = photoImage.draw(canvas); drawTime = photoImage.getVisible(); - } radialProgress.setHideCurrentDrawable(false); SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); @@ -1113,16 +1204,16 @@ public class ChatMediaCell extends ChatBaseCell { //infoPaint.setColor(0xff70b15c); infoPaint.setColor(color); docBackPaint.setColor(0xffdaf5c3); - ResourceLoader.docMenuOutDrawable.setColorFilter(themePrefs.getInt("chatRTimeColor", AndroidUtilities.getIntDarkerColor("themeColor", 0x15)), PorterDuff.Mode.SRC_IN); - menuDrawable = ResourceLoader.docMenuOutDrawable; + ResourceLoader.docMenuDrawable[0].setColorFilter(themePrefs.getInt("chatRTimeColor", AndroidUtilities.getIntDarkerColor("themeColor", 0x15)), PorterDuff.Mode.SRC_IN); + menuDrawable = ResourceLoader.docMenuDrawable[0]; namePaint.setColor(color); } else { //infoPaint.setColor(0xffa1adbb); color = themePrefs.getInt("chatLTextColor", 0xff000000); infoPaint.setColor(color); docBackPaint.setColor(0xffebf0f5); - ResourceLoader.docMenuInDrawable.setColorFilter(themePrefs.getInt("chatLTimeColor", 0xffa1adbb), PorterDuff.Mode.SRC_IN); - menuDrawable = ResourceLoader.docMenuInDrawable; + ResourceLoader.docMenuDrawable[1].setColorFilter(themePrefs.getInt("chatLTimeColor", 0xffa1adbb), PorterDuff.Mode.SRC_IN); + menuDrawable = ResourceLoader.docMenuDrawable[1]; namePaint.setColor(color); } @@ -1132,9 +1223,9 @@ public class ChatMediaCell extends ChatBaseCell { if (buttonState >= 0 && buttonState < 4) { if (!imageDrawn) { if (buttonState == 1 && !currentMessageObject.isSending()) { - radialProgress.swapBackground(ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOutOwner() ? 1 : 0]); + radialProgress.swapBackground(ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOutOwner() ? 1 : (isDrawSelectedBackground() ? 2 : 0)]); } else { - radialProgress.swapBackground(ResourceLoader.buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOutOwner() ? 1 : 0]); + radialProgress.swapBackground(ResourceLoader.buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOutOwner() ? 1 : (isDrawSelectedBackground() ? 2 : 0)]); } } else { if (buttonState == 1 && !currentMessageObject.isSending()) { @@ -1150,7 +1241,7 @@ public class ChatMediaCell extends ChatBaseCell { if (currentMessageObject.isOutOwner()) { radialProgress.setProgressColor(0xff81bd72); } else { - radialProgress.setProgressColor(0xffadbdcc); + radialProgress.setProgressColor(isDrawSelectedBackground() ? 0xff83b2c2 : 0xffadbdcc); } } else { if (buttonState == -1) { @@ -1217,10 +1308,10 @@ public class ChatMediaCell extends ChatBaseCell { infoPaint.setColor(0xffffffff); if (currentMessageObject.type == 1){ setDrawableBounds(ResourceLoader.mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dp(20)); - }else if (currentMessageObject.type == 3){ - setDrawableBounds(ResourceLoader.mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset2, AndroidUtilities.dp(35)); - }else{ - setDrawableBounds(ResourceLoader.mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dp(16.5f)); + } else if (currentMessageObject.type == 3){ + setDrawableBounds(ResourceLoader.mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + (isChat ? infoOffset2 : infoOffset), AndroidUtilities.dp(isChat ? 35 : 16.5f)); + } else{ + setDrawableBounds(ResourceLoader.mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dp(16.5f)); } ResourceLoader.mediaBackgroundDrawable.draw(canvas); @@ -1245,7 +1336,7 @@ public class ChatMediaCell extends ChatBaseCell { } } else if (currentMessageObject.type == 4) { if (nameLayout != null) { - locationAddressPaint.setColor(currentMessageObject.isOutOwner() ? 0xff70b15c : 0xff999999); + locationAddressPaint.setColor(currentMessageObject.isOutOwner() ? 0xff70b15c : (isDrawSelectedBackground() ? 0xff89b4c1 : 0xff999999)); canvas.save(); canvas.translate(nameOffsetX + photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(3)); @@ -1259,19 +1350,25 @@ public class ChatMediaCell extends ChatBaseCell { canvas.restore(); } } - } else if (currentMessageObject.type == 9) { + } else if (currentMessageObject.type == 8) { if (nameLayout != null) { if (infoLayout2 != null) { canvas.save(); - canvas.translate(photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(8)); + canvas.translate(captionX = photoImage.getImageX() + AndroidUtilities.dp(5), captionY = photoImage.getImageY() + photoHeight + AndroidUtilities.dp(6)); infoLayout2.draw(canvas); canvas.restore(); } - - canvas.save(); + if (pressedLink != null) { + canvas.drawPath(urlPath, urlPaint); + } + canvas.translate(photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(30));//8 - nameLayout.draw(canvas); - canvas.restore(); + try { + nameLayout.draw(canvas); + canvas.restore(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } if (infoLayout != null) { canvas.save(); @@ -1303,12 +1400,15 @@ public class ChatMediaCell extends ChatBaseCell { @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, true); - if (currentMessageObject.type == 8 && lastDownloadedGifMessage != null && lastDownloadedGifMessage.getId() == currentMessageObject.getId()) { + if (!photoNotSet || currentMessageObject.type == 8 && currentMessageObject.audioProgress != 1) { + if (currentMessageObject.type == 8 && currentMessageObject.audioProgress != 1) { + photoNotSet = false; buttonState = 2; didPressedButton(true); - } else if (!photoNotSet) { + } else { updateButtonState(true); } + } if (photoNotSet) { setMessageObject(currentMessageObject); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 5e229e83..03f683d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -24,17 +24,18 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ClickableSpan; +import android.util.Log; import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.ViewStructure; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MediaController; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -61,6 +62,7 @@ public class ChatMessageCell extends ChatBaseCell { private ImageReceiver linkImageView; private boolean isSmallImage; private boolean drawImageButton; + private boolean isGifDocument; private boolean drawLinkImageView; private boolean hasLinkPreview; private int linkPreviewHeight; @@ -171,6 +173,10 @@ public class ChatMessageCell extends ChatBaseCell { linkPreviewPressed = true; result = true; } + if (linkPreviewPressed && isGifDocument && buttonState == -1 && MediaController.getInstance().canAutoplayGifs()) { + linkPreviewPressed = false; + result = false; + } } else { if (descriptionLayout != null && y >= descriptionY) { try { @@ -218,9 +224,22 @@ public class ChatMessageCell extends ChatBaseCell { pressedLink.onClick(this); } else { if (drawImageButton && delegate != null) { + if (isGifDocument) { if (buttonState == -1) { - playSoundEffect(SoundEffectConstants.CLICK); + buttonState = 2; + currentMessageObject.audioProgress = 1; + linkImageView.setAllowStartAnimation(false); + linkImageView.stopAnimation(); + radialProgress.setBackground(getDrawableForCurrentState(), false, false); + invalidate(); + playSoundEffect(SoundEffectConstants.CLICK); + } else if (buttonState == 2 || buttonState == 0) { + didPressedButton(false); + playSoundEffect(SoundEffectConstants.CLICK); + } + } else if (buttonState == -1) { delegate.didClickedImage(this); + playSoundEffect(SoundEffectConstants.CLICK); } } else { TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage; @@ -313,7 +332,8 @@ public class ChatMessageCell extends ChatBaseCell { int addedChars = 0; StaticLayout layout = new StaticLayout(text, paint, smallWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); for (int a = 0; a < linesCount; a++) { - if (layout.getLineLeft(a) != 0) { + Layout.Directions directions = layout.getLineDirections(a); + if (layout.getLineLeft(a) != 0 || Build.VERSION.SDK_INT >= 14 && (layout.isRtlCharAt(layout.getLineStart(a)) || layout.isRtlCharAt(layout.getLineEnd(a)))) { maxWidth = smallWidth; } int pos = layout.getLineEnd(a); @@ -391,6 +411,7 @@ public class ChatMessageCell extends ChatBaseCell { linkPreviewHeight = 0; isInstagram = false; durationLayout = null; + isGifDocument = false; descriptionLayout = null; titleLayout = null; siteNameLayout = null; @@ -417,10 +438,12 @@ public class ChatMessageCell extends ChatBaseCell { if ((isChat || showAvatar) && !messageObject.isOutOwner() && messageObject.messageOwner.from_id > 0 || ( (showMyAvatar && !isChat) || (showMyAvatarGroup && isChat)) && messageObject.isOutOwner()) { maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122); + //Log.e("ChatMessageCell","1 DRAWNAME true maxWidth: " + maxWidth); drawName = true; } else { maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80); drawName = messageObject.messageOwner.to_id.channel_id != 0 && !messageObject.isOutOwner(); + //Log.e("ChatMessageCell","2 DRAWNAME x maxWidth: " + maxWidth); } } @@ -429,6 +452,7 @@ public class ChatMessageCell extends ChatBaseCell { super.setMessageObject(messageObject); backgroundWidth = messageObject.textWidth; + //Log.e("ChatMessageCell","3 textWidth: " + backgroundWidth); totalHeight = messageObject.textHeight + AndroidUtilities.dp(19.5f) + namesOffset; int maxChildWidth = Math.max(backgroundWidth, nameWidth); @@ -445,7 +469,6 @@ public class ChatMessageCell extends ChatBaseCell { if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPage) { int linkPreviewMaxWidth; if (AndroidUtilities.isTablet()) { - //Maybe linkPreviewMaxWidth needs a fix here for showmyavatar if (messageObject.messageOwner.from_id > 0 && (currentMessageObject.messageOwner.to_id.channel_id != 0 || currentMessageObject.messageOwner.to_id.chat_id != 0) && !currentMessageObject.isOut()) { //linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(122); linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(leftBound + 70); @@ -453,8 +476,8 @@ public class ChatMessageCell extends ChatBaseCell { linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80); } } else { - //Maybe linkPreviewMaxWidth needs a fix here for showmyavatar - if (messageObject.messageOwner.from_id > 0 && (currentMessageObject.messageOwner.to_id.channel_id != 0 || currentMessageObject.messageOwner.to_id.chat_id != 0) && !currentMessageObject.isOutOwner()) { + //if (messageObject.messageOwner.from_id > 0 && (currentMessageObject.messageOwner.to_id.channel_id != 0 || currentMessageObject.messageOwner.to_id.chat_id != 0) && !currentMessageObject.isOutOwner()) { + if (messageObject.messageOwner.from_id > 0 && (currentMessageObject.messageOwner.to_id.channel_id != 0 || currentMessageObject.messageOwner.to_id.chat_id != 0 || showAvatar) && !currentMessageObject.isOutOwner() || (showMyAvatar && currentMessageObject.isOutOwner())) { //linkPreviewMaxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122); linkPreviewMaxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(leftBound + 70); } else { @@ -620,7 +643,7 @@ public class ChatMessageCell extends ChatBaseCell { } else { width = hasRTL ? descriptionLayout.getWidth() : (int) Math.ceil(descriptionLayout.getLineWidth(a)); } - if (a < restLines || lineLeft != 0 && isSmallImage) { + if (a < restLines || restLines != 0 && lineLeft != 0 && isSmallImage) { width += AndroidUtilities.dp(48 + 2); } if (maxWebWidth < width + additinalWidth) { @@ -632,6 +655,14 @@ public class ChatMessageCell extends ChatBaseCell { } maxWebWidth = width + additinalWidth; } + if (restLines == 0 || !isSmallImage) { + if (titleIsRTL) { + titleX = -AndroidUtilities.dp(4); + } + if (authorIsRTL) { + authorX = -AndroidUtilities.dp(4); + } + } maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); } } catch (Exception e) { @@ -639,20 +670,30 @@ public class ChatMessageCell extends ChatBaseCell { } } - if (webPage.photo != null) { boolean smallImage = webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article")); if (smallImage && (descriptionLayout == null || descriptionLayout != null && descriptionLayout.getLineCount() == 1)) { smallImage = false; isSmallImage = false; } - drawImageButton = webPage.type != null && webPage.type.equals("photo"); int maxPhotoWidth = smallImage ? AndroidUtilities.dp(48) : linkPreviewMaxWidth; + + if (webPage.document != null && MessageObject.isGifDocument(webPage.document)) { + if (!MediaController.getInstance().canAutoplayGifs()) { + messageObject.audioProgress = 1; + } + linkImageView.setAllowStartAnimation(messageObject.audioProgress != 1); + currentPhotoObject = webPage.document.thumb; + isGifDocument = true; + } else if (webPage.photo != null) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, drawImageButton ? AndroidUtilities.getPhotoSize() : maxPhotoWidth, !drawImageButton); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 80); if (currentPhotoObjectThumb == currentPhotoObject) { currentPhotoObjectThumb = null; } + } + if (currentPhotoObject != null) { + drawImageButton = webPage.type != null && (webPage.type.equals("photo") || webPage.type.equals("document") || webPage.type.equals("gif")); if (linkPreviewHeight != 0) { linkPreviewHeight += AndroidUtilities.dp(2); totalHeight += AndroidUtilities.dp(2); @@ -674,7 +715,7 @@ public class ChatMessageCell extends ChatBaseCell { float scale = width / (float) maxPhotoWidth; width /= scale; height /= scale; - if (webPage.site_name != null && !webPage.site_name.toLowerCase().equals("instagram")) { + if (webPage.site_name == null || webPage.site_name != null && !webPage.site_name.toLowerCase().equals("instagram") && !isGifDocument) { if (height > AndroidUtilities.displaySize.y / 3) { height = AndroidUtilities.displaySize.y / 3; } @@ -693,17 +734,30 @@ public class ChatMessageCell extends ChatBaseCell { linkImageView.setImageCoords(0, 0, width, height); - String fileName = FileLoader.getAttachFileName(currentPhotoObject); + currentPhotoFilter = String.format(Locale.US, "%d_%d", width, height); + currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", width, height); + if (isGifDocument) { + boolean photoExist = true; + File cacheFile = FileLoader.getPathToAttach(webPage.document); + if (!cacheFile.exists()) { + photoExist = false; + } + String fileName = FileLoader.getAttachFileName(webPage.document); + if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_GIF) || FileLoader.getInstance().isLoadingFile(fileName)) { + photoNotSet = false; + linkImageView.setImage(webPage.document, null, currentPhotoObject.location, currentPhotoFilter, webPage.document.size, null, false); + } else { + photoNotSet = true; + linkImageView.setImage(null, null, currentPhotoObject.location, currentPhotoFilter, 0, null, false); + } + } else { boolean photoExist = true; File cacheFile = FileLoader.getPathToAttach(currentPhotoObject, true); if (!cacheFile.exists()) { photoExist = false; } - - currentPhotoFilter = String.format(Locale.US, "%d_%d", width, height); - currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", width, height); - + String fileName = FileLoader.getAttachFileName(currentPhotoObject); if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO) || FileLoader.getInstance().isLoadingFile(fileName)) { photoNotSet = false; linkImageView.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilterThumb, 0, null, false); @@ -715,6 +769,7 @@ public class ChatMessageCell extends ChatBaseCell { linkImageView.setImageBitmap((Drawable) null); } } + } drawLinkImageView = true; if (webPage.site_name != null) { @@ -725,7 +780,6 @@ public class ChatMessageCell extends ChatBaseCell { } } } - } if (webPage.type != null && webPage.type.equals("video") && webPage.duration != 0) { if (durationPaint == null) { @@ -751,12 +805,15 @@ public class ChatMessageCell extends ChatBaseCell { if (hasLinkPreview || maxWidth - messageObject.lastLineWidth < timeMore) { totalHeight += AndroidUtilities.dp(14); backgroundWidth = Math.max(maxChildWidth, messageObject.lastLineWidth) + AndroidUtilities.dp(29); + //Log.e("ChatMessageCell","4 backgroundWidth: " + backgroundWidth + " hasLinkPreview: " + hasLinkPreview + " maxChildWidth: " + maxChildWidth + " lastLineWidth: " + messageObject.lastLineWidth); } else { int diff = maxChildWidth - messageObject.lastLineWidth; if (diff >= 0 && diff <= timeMore) { backgroundWidth = maxChildWidth + timeMore - diff + AndroidUtilities.dp(29); + //Log.e("ChatMessageCell","5 backgroundWidth: " + backgroundWidth); } else { backgroundWidth = Math.max(maxChildWidth, messageObject.lastLineWidth + timeMore) + AndroidUtilities.dp(29); + //Log.e("ChatMessageCell","6 backgroundWidth: " + backgroundWidth); } } //Plus @@ -764,7 +821,10 @@ public class ChatMessageCell extends ChatBaseCell { if ((totalHeight < avatarSize)) { totalHeight = avatarSize + AndroidUtilities.dp(10); } - //totalHeight = messageObject.textHeight + AndroidUtilities.dp(19.5f) + namesOffset; + //Log.e("ChatMessageCell","7 " + backgroundWidth); + if(backgroundWidth > Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(leftBound + 70) && hasLinkPreview){ + //Log.e("ChatMessageCell","8 YES"); + } } } updateButtonState(dataChanged); @@ -959,8 +1019,16 @@ public class ChatMessageCell extends ChatBaseCell { if (currentPhotoObject == null || !drawImageButton) { return; } - String fileName = FileLoader.getAttachFileName(currentPhotoObject); - File cacheFile = FileLoader.getPathToAttach(currentPhotoObject, true); + String fileName; + File cacheFile; + + if (isGifDocument) { + fileName = FileLoader.getAttachFileName(currentMessageObject.messageOwner.media.webpage.document); + cacheFile = FileLoader.getPathToAttach(currentMessageObject.messageOwner.media.webpage.document); + } else { + fileName = FileLoader.getAttachFileName(currentPhotoObject); + cacheFile = FileLoader.getPathToAttach(currentPhotoObject, true); + } if (fileName == null) { radialProgress.setBackground(null, false, false); return; @@ -970,11 +1038,13 @@ public class ChatMessageCell extends ChatBaseCell { float setProgress = 0; boolean progressVisible = false; if (!FileLoader.getInstance().isLoadingFile(fileName)) { - if (cancelLoading || !MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { - buttonState = 0; - } else { + if (!cancelLoading && + (!isGifDocument && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO) || + isGifDocument && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_GIF)) ) { progressVisible = true; buttonState = 1; + } else { + buttonState = 0; } } else { progressVisible = true; @@ -987,7 +1057,11 @@ public class ChatMessageCell extends ChatBaseCell { invalidate(); } else { MediaController.getInstance().removeLoadingFileObserver(this); + if (isGifDocument && !linkImageView.isAllowStartAnimation()) { + buttonState = 2; + } else { buttonState = -1; + } radialProgress.setBackground(getDrawableForCurrentState(), false, animated); invalidate(); } @@ -997,7 +1071,12 @@ public class ChatMessageCell extends ChatBaseCell { if (buttonState == 0) { cancelLoading = false; radialProgress.setProgress(0, false); + if (isGifDocument) { + linkImageView.setImage(currentMessageObject.messageOwner.media.webpage.document, null, currentPhotoObject.location, currentPhotoFilter, currentMessageObject.messageOwner.media.webpage.document.size, null, false); + currentMessageObject.audioProgress = 2; + } else { linkImageView.setImage(currentPhotoObject.location, currentPhotoFilter, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, currentPhotoFilterThumb, 0, null, false); + } buttonState = 1; radialProgress.setBackground(getDrawableForCurrentState(), true, animated); invalidate(); @@ -1013,6 +1092,12 @@ public class ChatMessageCell extends ChatBaseCell { radialProgress.setBackground(getDrawableForCurrentState(), false, animated); invalidate(); } + } else if (buttonState == 2) { + linkImageView.setAllowStartAnimation(true); + linkImageView.startAnimation(); + currentMessageObject.audioProgress = 0; + buttonState = -1; + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); } } @@ -1024,7 +1109,10 @@ public class ChatMessageCell extends ChatBaseCell { @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, true); - if (!photoNotSet) { + if (isGifDocument && currentMessageObject.audioProgress != 1) { + buttonState = 2; + didPressedButton(true); + } else if (!photoNotSet) { updateButtonState(true); } else { setMessageObject(currentMessageObject); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 2a768b3d..6c060940 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -65,6 +65,7 @@ public class DialogCell extends BaseCell { private static Drawable countDrawable; private static Drawable countDrawableGrey; private static Drawable groupDrawable; + private static Drawable superGroupDrawable; private static Drawable broadcastDrawable; private static Drawable botDrawable; private static Drawable muteDrawable; @@ -95,6 +96,7 @@ public class DialogCell extends BaseCell { public boolean useSeparator = false; private int nameLeft; + private int nameTop = AndroidUtilities.dp(13); private StaticLayout nameLayout; private boolean drawNameLock; private boolean drawNameGroup; @@ -142,6 +144,8 @@ public class DialogCell extends BaseCell { private GradientDrawable statusBG; private boolean drawStatus; + private boolean twoLinesMsg = false; + public DialogCell(Context context) { super(context); @@ -206,6 +210,7 @@ public class DialogCell extends BaseCell { countDrawable = getResources().getDrawable(R.drawable.dialogs_badge); countDrawableGrey = getResources().getDrawable(R.drawable.dialogs_badge2); groupDrawable = getResources().getDrawable(R.drawable.list_group); + superGroupDrawable = getResources().getDrawable(R.drawable.list_supergroup); broadcastDrawable = getResources().getDrawable(R.drawable.list_broadcast); muteDrawable = getResources().getDrawable(R.drawable.mute_grey); verifiedDrawable = getResources().getDrawable(R.drawable.check_list); @@ -331,9 +336,11 @@ public class DialogCell extends BaseCell { if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + //nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + //nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); nameLeft = AndroidUtilities.dp(14); } } else { @@ -437,23 +444,23 @@ public class DialogCell extends BaseCell { checkMessage = false; SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); - String hexMsgColor = String.format("#%08X", (0xffffffff & themePrefs.getInt("chatsMessageColor", 0xff808080))); + String hexMsgColor = String.format("#%08X", themePrefs.getInt("chatsMessageColor", 0xff808080)); int darkColor = themePrefs.getInt("chatsMemberColor", AndroidUtilities.getIntDarkerColor("themeColor", 0x15)); - String hexDarkColor = String.format("#%08X", (0xffffffff & darkColor)); - String hexMediaColor = String.format("#%08X", (0xffffffff & themePrefs.getInt("chatsMediaColor", darkColor))); + String hexDarkColor = String.format("#%08X", darkColor); + String hexMediaColor = String.format("#%08X", themePrefs.getInt("chatsMediaColor", darkColor)); if (message.caption != null) { String mess = message.caption.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = messagePrintingPaint; - //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText)), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), message.messageText)), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { if (message.messageOwner.message != null) { String mess = message.messageOwner.message; @@ -461,8 +468,8 @@ public class DialogCell extends BaseCell { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess)), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + //messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), mess)), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name.replace("\n", ""), mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } } } @@ -564,7 +571,8 @@ public class DialogCell extends BaseCell { if (drawNameLock) { nameWidth -= AndroidUtilities.dp(4) + lockDrawable.getIntrinsicWidth(); } else if (drawNameGroup) { - nameWidth -= AndroidUtilities.dp(4) + groupDrawable.getIntrinsicWidth(); + //nameWidth -= AndroidUtilities.dp(4) + groupDrawable.getIntrinsicWidth(); + nameWidth -= AndroidUtilities.dp(4) + (chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth()); } else if (drawNameBroadcast) { nameWidth -= AndroidUtilities.dp(4) + broadcastDrawable.getIntrinsicWidth(); } else if (drawNameBot) { @@ -677,7 +685,22 @@ public class DialogCell extends BaseCell { messageWidth = Math.max(AndroidUtilities.dp(12), messageWidth); CharSequence messageStringFinal = TextUtils.ellipsize(messageString, currentMessagePaint, messageWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); try { - messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if(twoLinesMsg){ + messageLayout = new StaticLayout(messageString, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if(messageLayout.getLineCount() > 1){ + messageTop = AndroidUtilities.dp(32); + nameTop = AndroidUtilities.dp(8); + timeTop = AndroidUtilities.dp(10); + checkDrawTop = AndroidUtilities.dp(12); + nameLockTop = AndroidUtilities.dp(12); + }else{ + messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + }else{ + nameLockTop = AndroidUtilities.dp(16.5f); + messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + //messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -748,6 +771,23 @@ public class DialogCell extends BaseCell { } else if (dialogsType == 2) { return MessagesController.getInstance().dialogsGroupsOnly; } + //plus + else if (dialogsType == 3) { + return MessagesController.getInstance().dialogsUsers; + } else if (dialogsType == 4) { + return MessagesController.getInstance().dialogsGroups; + } else if (dialogsType == 5) { + return MessagesController.getInstance().dialogsChannels; + } else if (dialogsType == 6) { + return MessagesController.getInstance().dialogsBots; + } else if (dialogsType == 7) { + return MessagesController.getInstance().dialogsMegaGroups; + } else if (dialogsType == 8) { + return MessagesController.getInstance().dialogsFavs; + } else if (dialogsType == 9) { + return MessagesController.getInstance().dialogsGroupsAll; + } + // return null; } @@ -915,7 +955,7 @@ public class DialogCell extends BaseCell { groupPaint.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatsGroupNameSize", themePrefs.getInt("chatsNameSize", 17)))); groupPaint.setColor(themePrefs.getInt("chatsGroupNameColor", nColor)); - lockDrawable.setColorFilter(themePrefs.getInt("chatsNameColor", tColor), PorterDuff.Mode.SRC_IN); + lockDrawable.setColorFilter(themePrefs.getInt("chatsGroupIconColor", themePrefs.getInt("chatsNameColor", tColor)), PorterDuff.Mode.SRC_IN); nameEncryptedPaint.setTextSize(AndroidUtilities.dp(themePrefs.getInt("chatsNameSize", 17))); nameEncryptedPaint.setColor(themePrefs.getInt("chatsNameColor", dColor));//0xff00a60e @@ -949,6 +989,7 @@ public class DialogCell extends BaseCell { nColor = themePrefs.getInt("chatsGroupIconColor", themePrefs.getInt("chatsGroupNameColor", 0xff000000)); groupDrawable.setColorFilter(nColor, PorterDuff.Mode.SRC_IN); + superGroupDrawable.setColorFilter(nColor, PorterDuff.Mode.SRC_IN); broadcastDrawable.setColorFilter(nColor, PorterDuff.Mode.SRC_IN); botDrawable.setColorFilter(nColor, PorterDuff.Mode.SRC_IN); @@ -981,8 +1022,15 @@ public class DialogCell extends BaseCell { setDrawableBounds(lockDrawable, nameLockLeft, nameLockTop); lockDrawable.draw(canvas); } else if (drawNameGroup) { - setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); - groupDrawable.draw(canvas); + //setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); + //groupDrawable.draw(canvas); + if(chat.megagroup){ + setDrawableBounds(superGroupDrawable , nameLockLeft, nameLockTop); + superGroupDrawable.draw(canvas); + }else{ + setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); + groupDrawable.draw(canvas); + } } else if (drawNameBroadcast) { setDrawableBounds(broadcastDrawable, nameLockLeft, nameLockTop); broadcastDrawable.draw(canvas); @@ -993,7 +1041,8 @@ public class DialogCell extends BaseCell { if (nameLayout != null) { canvas.save(); - canvas.translate(nameLeft, AndroidUtilities.dp(13)); + //canvas.translate(nameLeft, AndroidUtilities.dp(13)); + canvas.translate(nameLeft, nameTop); nameLayout.draw(canvas); canvas.restore(); } @@ -1026,10 +1075,12 @@ public class DialogCell extends BaseCell { } if (dialogMuted && !drawVerified) { - setDrawableBounds(muteDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + //setDrawableBounds(muteDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + setDrawableBounds(muteDrawable, nameMuteLeft, nameLockTop); muteDrawable.draw(canvas); } else if (drawVerified) { - setDrawableBounds(verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + //setDrawableBounds(verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + setDrawableBounds(verifiedDrawable, nameMuteLeft, nameLockTop); verifiedDrawable.draw(canvas); } SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java index f3b795a3..f09b7f13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java index 4ee4985a..b1f487a9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index 9a661491..914b3066 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -29,6 +29,7 @@ import android.widget.TextView; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.UserObject; @@ -152,7 +153,9 @@ public class DrawerProfileCell extends FrameLayout implements PhotoViewer.PhotoV FileLog.e("tmessages", e); } } - if(AndroidUtilities.getBoolMain("hideMobile")){ + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + if(plusPreferences.getBoolean("hideMobile", false) && !plusPreferences.getBoolean("showUsername", false)){ phoneTextView.setVisibility(GONE); }else{ phoneTextView.setVisibility(VISIBLE); @@ -203,7 +206,19 @@ public class DrawerProfileCell extends FrameLayout implements PhotoViewer.PhotoV photo = user.photo.photo_small; } nameTextView.setText(UserObject.getUserName(user)); - phoneTextView.setText(PhoneFormat.getInstance().format("+" + user.phone)); + //phoneTextView.setText(PhoneFormat.getInstance().format("+" + user.phone)); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + String value; + if(preferences.getBoolean("showUsername", false)) { + if (user.username != null && user.username.length() != 0) { + value = "@" + user.username; + } else { + value = LocaleController.getString("UsernameEmpty", R.string.UsernameEmpty); + } + } else{ + value = PhoneFormat.getInstance().format("+" + user.phone); + } + phoneTextView.setText(value); AvatarDrawable avatarDrawable = new AvatarDrawable(user); avatarDrawable.setColor(0xff5c98cd); avatarImageView.setImage(photo, "50_50", avatarDrawable); @@ -303,7 +318,10 @@ public class DrawerProfileCell extends FrameLayout implements PhotoViewer.PhotoV nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, themePrefs.getInt("drawerNameSize", 15)); phoneTextView.setTextColor(themePrefs.getInt("drawerPhoneColor", dColor)); phoneTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, themePrefs.getInt("drawerPhoneSize", 13)); - if(AndroidUtilities.getBoolMain("hideMobile")){ + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + + if(plusPreferences.getBoolean("hideMobile", false) && !plusPreferences.getBoolean("showUsername", false)){ phoneTextView.setVisibility(GONE); }else{ phoneTextView.setVisibility(VISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java index 53b3ca3a..522043d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java index 93b931cf..4e5bc7d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java index bd0cb55e..0b6947b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index cc541400..ad02a6c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java index d7f5005c..5e327553 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java index 6d8ba1d4..161f21c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java index 548202dd..53e5f686 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java index 84ab570d..3d12155e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java index 6b0b0677..b813baa7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index f952ae1a..aa0c9bff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -60,7 +60,7 @@ public class MentionCell extends LinearLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); } public void setUser(TLRPC.User user) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java index 8e16a1cc..89584407 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java index fc45e904..7fc1d5ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java index 620d2312..e39fb48a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java index 0b71286e..cfeb5a5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -21,6 +21,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; @@ -81,7 +82,7 @@ public class PhotoPickerSearchCell extends LinearLayout { private PhotoPickerSearchCellDelegate delegate; - public PhotoPickerSearchCell(Context context) { + public PhotoPickerSearchCell(Context context, boolean allowGifs) { super(context); setOrientation(HORIZONTAL); @@ -125,6 +126,7 @@ public class PhotoPickerSearchCell extends LinearLayout { layoutParams.height = AndroidUtilities.dp(48); layoutParams.width = 0; searchButton.setLayoutParams(layoutParams); + if (allowGifs) { searchButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -133,6 +135,9 @@ public class PhotoPickerSearchCell extends LinearLayout { } } }); + } else { + ViewProxy.setAlpha(searchButton, 0.5f); + } } public void setDelegate(PhotoPickerSearchCellDelegate delegate) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 5795befe..beb03cf5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -47,6 +47,7 @@ public class ProfileSearchCell extends BaseCell { private static Drawable botDrawable; private static Drawable broadcastDrawable; private static Drawable groupDrawable; + private static Drawable superGroupDrawable; private static Drawable countDrawable; private static Drawable countDrawableGrey; private static Drawable checkDrawable; @@ -126,6 +127,7 @@ public class ProfileSearchCell extends BaseCell { broadcastDrawable = getResources().getDrawable(R.drawable.list_broadcast); lockDrawable = getResources().getDrawable(R.drawable.list_secret); groupDrawable = getResources().getDrawable(R.drawable.list_group); + superGroupDrawable = getResources().getDrawable(R.drawable.list_supergroup); countDrawable = getResources().getDrawable(R.drawable.dialogs_badge); countDrawableGrey = getResources().getDrawable(R.drawable.dialogs_badge2); checkDrawable = getResources().getDrawable(R.drawable.check_list); @@ -239,9 +241,11 @@ public class ProfileSearchCell extends BaseCell { drawCheck = chat.verified; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + //nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + //nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - (drawNameGroup ? chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); nameLeft = AndroidUtilities.dp(11); } } else { @@ -304,7 +308,8 @@ public class ProfileSearchCell extends BaseCell { } else if (drawNameBroadcast) { nameWidth -= AndroidUtilities.dp(6) + broadcastDrawable.getIntrinsicWidth(); } else if (drawNameGroup) { - nameWidth -= AndroidUtilities.dp(6) + groupDrawable.getIntrinsicWidth(); + //nameWidth -= AndroidUtilities.dp(6) + groupDrawable.getIntrinsicWidth(); + nameWidth -= AndroidUtilities.dp(6) + (chat.megagroup ? superGroupDrawable.getIntrinsicWidth() : groupDrawable.getIntrinsicWidth()); } else if (drawNameBot) { nameWidth -= AndroidUtilities.dp(6) + botDrawable.getIntrinsicWidth(); } @@ -523,8 +528,15 @@ public class ProfileSearchCell extends BaseCell { setDrawableBounds(lockDrawable, nameLockLeft, nameLockTop); lockDrawable.draw(canvas); } else if (drawNameGroup) { - setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); - groupDrawable.draw(canvas); + //setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); + //groupDrawable.draw(canvas); + if(chat.megagroup){ + setDrawableBounds(superGroupDrawable, nameLockLeft, nameLockTop); + superGroupDrawable.draw(canvas); + }else{ + setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); + groupDrawable.draw(canvas); + } } else if (drawNameBroadcast) { setDrawableBounds(broadcastDrawable, nameLockLeft, nameLockTop); broadcastDrawable.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java index d6fe2833..e78a8c39 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index 2115f261..29faa0cc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java index e391e8d6..008f4bd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java index 6c6572a9..ca9494ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index 9baed23c..a5b6cca6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java index b4631b4d..3e2c8dd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 4ab37ad3..36214478 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java index af2d4baf..5f51556e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index d450fe34..ebbdb4da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java index 3361937f..c9a9fee6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index def50359..b8573343 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -3,12 +3,13 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; import android.content.Context; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.TypedValue; @@ -89,12 +90,8 @@ public class TextCell extends FrameLayout { textView.setTextSize(size); } - public void setTextAndIcon(String text, Drawable drawable) { - textView.setText(text); - imageView.setImageDrawable(drawable); - imageView.setVisibility(VISIBLE); - valueTextView.setVisibility(GONE); - valueImageView.setVisibility(GONE); + public void setIconColor(int color) { + imageView.setColorFilter(color, PorterDuff.Mode.SRC_IN); } public void setValueColor(int color) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java index 7665d0fd..0c93c243 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index 975e7c04..bd62e532 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java index dd728658..ae09d6ac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java index 7b6da298..32398e9b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java index 47dff3d6..b7008102 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java index 679783f1..5ef37d63 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; @@ -41,7 +41,7 @@ public class TextInfoPrivacyCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); setTheme(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java index 3d86232c..c2d64afb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index d2f1ecd7..23c38fd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java index 6d0ab6c1..9611068a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index 4b5dada9..1c4575d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -13,7 +13,9 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.text.InputFilter; import android.text.InputType; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -26,8 +28,11 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.query.BotQuery; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; @@ -41,10 +46,13 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.LayoutHelper; +import java.util.ArrayList; + public class ChangeNameActivity extends BaseFragment { private EditText firstNameField; private EditText lastNameField; + private EditText userStatusField; private View headerLabelView; private View doneButton; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index 3926c48d..c687be34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -413,7 +413,7 @@ public class ChangePhoneActivity extends BaseFragment { ignoreSelection = true; countryButton.setText(countriesArray.get(index)); String hint = phoneFormatMap.get(text); - phoneField.setHintText(hint != null ? hint.replace('X', '�') : null); + phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); countryState = 0; } else { countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); @@ -624,7 +624,7 @@ public class ChangePhoneActivity extends BaseFragment { codeField.setText(code); countryButton.setText(name); String hint = phoneFormatMap.get(code); - phoneField.setHintText(hint != null ? hint.replace('X', '�') : null); + phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); countryState = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java index 904a1467..b68b2fb1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index a9cb7a23..14e5a754 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 855050a0..0b46adbd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -29,11 +29,14 @@ import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.provider.Browser; import android.provider.ContactsContract; import android.provider.MediaStore; import android.text.TextUtils; import android.text.style.ClickableSpan; import android.util.Base64; +import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; @@ -43,7 +46,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.webkit.MimeTypeMap; -import android.widget.AdapterView; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; @@ -195,7 +197,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private TextView replyObjectTextView; private ImageView replyIconImageView; private MentionsAdapter mentionsAdapter; - private ListView mentionListView; + private RecyclerListView mentionListView; + private LinearLayoutManager mentionLayoutManager; private AnimatorSetProxy mentionListAnimation; private ChatAttachView chatAttachView; private BottomSheet chatAttachViewSheet; @@ -204,6 +207,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private TextView reportSpamButton; private FrameLayout reportSpamContainer; private PlayerView playerView; + private TextView gifHintTextView; + private View emojiButtonRed; private ObjectAnimatorProxy pagedownButtonAnimation; private AnimatorSetProxy replyButtonAnimation; @@ -218,6 +223,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private View lineView; private boolean allowStickersPanel; + private boolean allowContextBotPanel; + private boolean allowContextBotPanelSecond = true; private AnimatorSetProxy runningAnimation; private MessageObject selectedObject; @@ -352,6 +359,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean quote; + private TextView dateTv; + RecyclerListView.OnItemLongClickListener onItemLongClickListener = new RecyclerListView.OnItemLongClickListener() { @Override public boolean onItemClick(View view, int position) { @@ -712,6 +721,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not //actionBar.setBackButtonDrawable(new BackDrawable(false)); SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int tColor = themePrefs.getInt("chatsHeaderTitleColor", 0xffffffff); Drawable d = new BackDrawable(false); ((BackDrawable) d).setColor(themePrefs.getInt("chatHeaderIconsColor", 0xffffffff)); actionBar.setBackButtonDrawable(d); @@ -719,40 +729,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onItemClick(final int id) { if (id == -1) { - if (actionBar.isActionModeShowed()) { - for (int a = 1; a >= 0; a--) { - selectedMessagesIds[a].clear(); - selectedMessagesCanCopyIds[a].clear(); + if (actionBar.isActionModeShowed()) { + for (int a = 1; a >= 0; a--) { + selectedMessagesIds[a].clear(); + selectedMessagesCanCopyIds[a].clear(); + } + cantDeleteMessagesCount = 0; + actionBar.hideActionMode(); + updateVisibleRows(); + } else { + finishFragment(); } - cantDeleteMessagesCount = 0; - actionBar.hideActionMode(); - updateVisibleRows(); - } else { - finishFragment(); - } } else if (id == copy) { String str = ""; - for (int a = 1; a >= 0; a--) { - ArrayList ids = new ArrayList<>(selectedMessagesCanCopyIds[a].keySet()); - if (currentEncryptedChat == null) { - Collections.sort(ids); - } else { - Collections.sort(ids, Collections.reverseOrder()); - } - for (int b = 0; b < ids.size(); b++) { - Integer messageId = ids.get(b); - MessageObject messageObject = selectedMessagesCanCopyIds[a].get(messageId); - if (str.length() != 0) { - str += "\n"; - } - if (messageObject.messageOwner.message != null) { - str += messageObject.messageOwner.message; + for (int a = 1; a >= 0; a--) { + ArrayList ids = new ArrayList<>(selectedMessagesCanCopyIds[a].keySet()); + if (currentEncryptedChat == null) { + Collections.sort(ids); } else { - str += messageObject.messageText; + Collections.sort(ids, Collections.reverseOrder()); + } + for (int b = 0; b < ids.size(); b++) { + Integer messageId = ids.get(b); + MessageObject messageObject = selectedMessagesCanCopyIds[a].get(messageId); + if (str.length() != 0) { + str += "\n"; + } + if (messageObject.messageOwner.message != null) { + str += messageObject.messageOwner.message; + } else { + str += messageObject.messageText; + } } } - } if (str.length() != 0) { + try { if (Build.VERSION.SDK_INT < 11) { android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText(str); @@ -761,6 +772,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not android.content.ClipData clip = android.content.ClipData.newPlainText("label", str); clipboard.setPrimaryClip(clip); } + } catch (Exception e) { + FileLog.e("tmessages", e); + } } for (int a = 1; a >= 0; a--) { selectedMessagesIds[a].clear(); @@ -813,8 +827,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } Bundle args = new Bundle(); args.putBoolean("onlySelect", true); - args.putInt("dialogsType", 1); - DialogsActivity fragment = new DialogsActivity(args); + args.putInt("dialogsType", 1); + DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } else if (id == chat_enc_timer) { @@ -843,17 +857,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onClick(DialogInterface dialogInterface, int i) { if (id != clear_history) { if (isChat) { - if (ChatObject.isNotInChat(currentChat)) { - MessagesController.getInstance().deleteDialog(dialog_id, false); + if (ChatObject.isNotInChat(currentChat)) { + MessagesController.getInstance().deleteDialog(dialog_id, 0); + } else { + MessagesController.getInstance().deleteUserFromChat((int) -dialog_id, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + } } else { - MessagesController.getInstance().deleteUserFromChat((int) -dialog_id, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); + MessagesController.getInstance().deleteDialog(dialog_id, 0); } + finishFragment(); } else { - MessagesController.getInstance().deleteDialog(dialog_id, false); - } - finishFragment(); - } else { - MessagesController.getInstance().deleteDialog(dialog_id, true); + MessagesController.getInstance().deleteDialog(dialog_id, 1); } } }); @@ -936,8 +950,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return; } else { + if (chatAttachViewSheet != null) { chatAttachViewSheet.dismissWithButtonClick(button); } + } processSelectedAttach(button); } }); @@ -988,9 +1004,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAttachView.init(ChatActivity.this); showDialog(chatAttachViewSheet); } else if (id == bot_help) { - SendMessagesHelper.getInstance().sendMessage("/help", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); + SendMessagesHelper.getInstance().sendMessage("/help", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin(), null, null); } else if (id == bot_settings) { - SendMessagesHelper.getInstance().sendMessage("/settings", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); + SendMessagesHelper.getInstance().sendMessage("/settings", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin(), null, null); } else if (id == search) { openSearchWithText(null); } else if (id == search_up) { @@ -1013,10 +1029,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); avatarContainer = new FrameLayoutFixed(context); - avatarContainer.setBackgroundResource(R.drawable.bar_selector); - avatarContainer.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + avatarContainer.setBackgroundResource(R.drawable.bar_selector); + avatarContainer.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0)); - avatarContainer.setOnClickListener(new View.OnClickListener() { + avatarContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (radioButton == null || radioButton.getVisibility() != View.VISIBLE) { @@ -1183,8 +1199,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not headerItem.addSubItem(open_channel_profile, LocaleController.getString("OpenChannelProfile", R.string.OpenChannelProfile), 0); } try{ - final boolean isChat = (int) dialog_id < 0 && (int) (dialog_id >> 32) != 1; - if(isChat)headerItem.addSubItem(add_member, LocaleController.getString("AddMember", R.string.AddMember), 0); + if (chat_id > 0) { + if (ChatObject.isChannel(currentChat)) { + if (/*currentChat.megagroup &&*/ (currentChat.editor || currentChat.creator)) { + if (info == null || info.participants_count < MessagesController.getInstance().maxMegagroupCount) { + headerItem.addSubItem(add_member, LocaleController.getString("AddMember", R.string.AddMember), 0); + } + } + } else { + if (currentChat.admin || currentChat.creator || !currentChat.admins_enabled) { + headerItem.addSubItem(add_member, LocaleController.getString("AddMember", R.string.AddMember), 0); + } + } + } headerItem.addSubItem(chat_background, LocaleController.getString("ChatBackground", R.string.ChatBackground), 0); //!Plus if (searchItem != null) { @@ -1245,10 +1272,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); if (currentEncryptedChat == null) { - actionModeViews.add(actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); if (!isBroadcast) { actionModeViews.add(actionMode.addItem(reply, R.drawable.ic_ab_reply, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); } + actionModeViews.add(actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); actionModeViews.add(actionMode.addItem(quoteforward, R.drawable.ic_ab_fwd_quoteforward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); actionModeViews.add(actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); actionModeViews.add(actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); @@ -1285,7 +1312,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < childCount; i++) { View child = getChildAt(i); - if (child.getVisibility() == GONE || child == chatActivityEnterView) { + if (child == null || child.getVisibility() == GONE || child == chatActivityEnterView) { continue; } try { @@ -1370,6 +1397,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not childTop -= inputFieldHeight / 2; } else if (chatActivityEnterView.isPopupView(child)) { childTop = chatActivityEnterView.getBottom(); + } else if (child == gifHintTextView) { + childTop -= inputFieldHeight; } child.layout(childLeft, childTop, childLeft + width, childTop + height); } @@ -1382,92 +1411,100 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not //contentView.setBackgroundImage(ApplicationLoader.getCachedWallpaper()); updateBackground(contentView); emptyViewContainer = new FrameLayout(context); - emptyViewContainer.setVisibility(View.INVISIBLE); + emptyViewContainer.setVisibility(View.INVISIBLE); contentView.addView(emptyViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - emptyViewContainer.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); + emptyViewContainer.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); - if (currentEncryptedChat == null) { + Drawable dSystem = context.getResources().getDrawable(R.drawable.system_white); + dSystem.setColorFilter(themePrefs.getInt("chatDateBubbleColor", 0x59000000), PorterDuff.Mode.SRC_IN); + int dColor = themePrefs.getInt("chatDateColor", 0xffffffff); + if (currentEncryptedChat == null) { TextView emptyView = new TextView(context); if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && (currentUser.id / 1000 == 333 || currentUser.id % 1000 == 0)) { - emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); - } else { - emptyView.setText(LocaleController.getString("NoMessages", R.string.NoMessages)); - } - emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - emptyView.setGravity(Gravity.CENTER); - //emptyView.setTextColor(0xffffffff); - emptyView.setTextColor(themePrefs.getInt("chatDateColor", 0xffffffff)); - emptyView.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); - emptyView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(1), AndroidUtilities.dp(7), AndroidUtilities.dp(1)); - emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); } else { + emptyView.setText(LocaleController.getString("NoMessages", R.string.NoMessages)); + } + emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + emptyView.setGravity(Gravity.CENTER); + //emptyView.setTextColor(0xffffffff); + emptyView.setTextColor(dColor); + //emptyView.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); + emptyView.setBackgroundDrawable(dSystem); + emptyView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(1), AndroidUtilities.dp(7), AndroidUtilities.dp(1)); + emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + } else { LinearLayout secretChatPlaceholder = new LinearLayout(context); - secretChatPlaceholder.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); - secretChatPlaceholder.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(12), AndroidUtilities.dp(16), AndroidUtilities.dp(12)); - secretChatPlaceholder.setOrientation(LinearLayout.VERTICAL); + //secretChatPlaceholder.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); + secretChatPlaceholder.setBackgroundDrawable(dSystem); + secretChatPlaceholder.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(12), AndroidUtilities.dp(16), AndroidUtilities.dp(12)); + secretChatPlaceholder.setOrientation(LinearLayout.VERTICAL); emptyViewContainer.addView(secretChatPlaceholder, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); secretViewStatusTextView = new TextView(context); - secretViewStatusTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - secretViewStatusTextView.setTextColor(0xffffffff); - secretViewStatusTextView.setGravity(Gravity.CENTER_HORIZONTAL); - secretViewStatusTextView.setMaxWidth(AndroidUtilities.dp(210)); - if (currentEncryptedChat.admin_id == UserConfig.getClientUserId()) { + secretViewStatusTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + //secretViewStatusTextView.setTextColor(0xffffffff); + secretViewStatusTextView.setTextColor(dColor); + secretViewStatusTextView.setGravity(Gravity.CENTER_HORIZONTAL); + secretViewStatusTextView.setMaxWidth(AndroidUtilities.dp(210)); + if (currentEncryptedChat.admin_id == UserConfig.getClientUserId()) { secretViewStatusTextView.setText(LocaleController.formatString("EncryptedPlaceholderTitleOutgoing", R.string.EncryptedPlaceholderTitleOutgoing, UserObject.getFirstName(currentUser))); } else { secretViewStatusTextView.setText(LocaleController.formatString("EncryptedPlaceholderTitleIncoming", R.string.EncryptedPlaceholderTitleIncoming, UserObject.getFirstName(currentUser))); - } + } secretChatPlaceholder.addView(secretViewStatusTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); TextView textView = new TextView(context); - textView.setText(LocaleController.getString("EncryptedDescriptionTitle", R.string.EncryptedDescriptionTitle)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setTextColor(0xffffffff); - textView.setGravity(Gravity.CENTER_HORIZONTAL); - textView.setMaxWidth(AndroidUtilities.dp(260)); + textView.setText(LocaleController.getString("EncryptedDescriptionTitle", R.string.EncryptedDescriptionTitle)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + //textView.setTextColor(0xffffffff); + textView.setTextColor(dColor); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + textView.setMaxWidth(AndroidUtilities.dp(260)); secretChatPlaceholder.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 0, 8, 0, 0)); - for (int a = 0; a < 4; a++) { + for (int a = 0; a < 4; a++) { LinearLayout linearLayout = new LinearLayout(context); - linearLayout.setOrientation(LinearLayout.HORIZONTAL); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); secretChatPlaceholder.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 8, 0, 0)); ImageView imageView = new ImageView(context); - imageView.setImageResource(R.drawable.ic_lock_white); + imageView.setImageResource(R.drawable.ic_lock_white); textView = new TextView(context); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setTextColor(0xffffffff); - textView.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - textView.setMaxWidth(AndroidUtilities.dp(260)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + //textView.setTextColor(0xffffffff); + textView.setTextColor(dColor); + textView.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); + textView.setMaxWidth(AndroidUtilities.dp(260)); - switch (a) { - case 0: - textView.setText(LocaleController.getString("EncryptedDescription1", R.string.EncryptedDescription1)); - break; - case 1: - textView.setText(LocaleController.getString("EncryptedDescription2", R.string.EncryptedDescription2)); - break; - case 2: - textView.setText(LocaleController.getString("EncryptedDescription3", R.string.EncryptedDescription3)); - break; - case 3: - textView.setText(LocaleController.getString("EncryptedDescription4", R.string.EncryptedDescription4)); - break; - } + switch (a) { + case 0: + textView.setText(LocaleController.getString("EncryptedDescription1", R.string.EncryptedDescription1)); + break; + case 1: + textView.setText(LocaleController.getString("EncryptedDescription2", R.string.EncryptedDescription2)); + break; + case 2: + textView.setText(LocaleController.getString("EncryptedDescription3", R.string.EncryptedDescription3)); + break; + case 3: + textView.setText(LocaleController.getString("EncryptedDescription4", R.string.EncryptedDescription4)); + break; + } - if (LocaleController.isRTL) { + if (LocaleController.isRTL) { linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 8, 3, 0, 0)); - } else { + } else { linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 4, 8, 0)); linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - } + } } } @@ -1497,8 +1534,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }; chatListView.setVerticalScrollBarEnabled(true); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); - chatListView.setClipToPadding(false); - chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); + chatListView.setClipToPadding(false); + chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); chatListView.setItemAnimator(null); chatListView.setLayoutAnimation(null); chatLayoutManager = new LinearLayoutManager(context) { @@ -1521,6 +1558,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not highlightMessageId = Integer.MAX_VALUE; updateVisibleRows(); } + + if(newState == 0){ + hideDateTv(); + } } @Override @@ -1535,6 +1576,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } updateMessagesVisisblePart(); + if(dy != 0){ + updateDateToast(); + } } }); chatListView.setOnTouchListener(new View.OnTouchListener() { @@ -1646,7 +1690,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); progressView = new FrameLayout(context); - progressView.setVisibility(View.INVISIBLE); + progressView.setVisibility(View.INVISIBLE); contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); View view = new View(context); @@ -1674,10 +1718,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not addToContactsButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); addToContactsButton.setSingleLine(true); addToContactsButton.setMaxLines(1); - addToContactsButton.setPadding(AndroidUtilities.dp(50), 0, AndroidUtilities.dp(4), 0); + addToContactsButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); addToContactsButton.setGravity(Gravity.CENTER); addToContactsButton.setText(LocaleController.getString("AddContactChat", R.string.AddContactChat)); - reportSpamView.addView(addToContactsButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0.5f, Gravity.LEFT | Gravity.TOP)); + reportSpamView.addView(addToContactsButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0.5f, Gravity.LEFT | Gravity.TOP, 0, 0, 0, AndroidUtilities.dp(1))); addToContactsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -1761,13 +1805,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); if (currentEncryptedChat == null && !isBroadcast) { - mentionListView = new ListView(context); + mentionListView = new RecyclerListView(context); + mentionLayoutManager = new LinearLayoutManager(context) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + mentionLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + mentionListView.setLayoutManager(mentionLayoutManager); + mentionListView.setBackgroundResource(R.drawable.compose_panel); mentionListView.setVisibility(View.GONE); mentionListView.setPadding(0, AndroidUtilities.dp(2), 0, 0); mentionListView.setClipToPadding(true); - mentionListView.setDividerHeight(0); - mentionListView.setDivider(null); + mentionListView.setDisallowInterceptTouchEvents(true); if (Build.VERSION.SDK_INT > 8) { mentionListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER); } @@ -1777,12 +1829,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void needChangePanelVisibility(boolean show) { if (show) { + int orientation = mentionsAdapter.getOrientation(); + FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) mentionListView.getLayoutParams(); - int height = 36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0); + int height; + if (orientation == LinearLayoutManager.HORIZONTAL) { + mentionListView.setPadding(0, AndroidUtilities.dp(2), AndroidUtilities.dp(5), 0); + mentionListView.setClipToPadding(false); + height = 90; + } else { + mentionListView.setPadding(0, AndroidUtilities.dp(2), 0, 0); + mentionListView.setClipToPadding(true); + if (mentionsAdapter.isBotContext()) { + height = 36 * 3 + 18; + } else { + height = 36 * Math.min(3, mentionsAdapter.getItemCount()) + (mentionsAdapter.getItemCount() > 3 ? 18 : 0); + } + } layoutParams3.height = AndroidUtilities.dp(2 + height); layoutParams3.topMargin = -AndroidUtilities.dp(height); mentionListView.setLayoutParams(layoutParams3); + mentionLayoutManager.setOrientation(orientation); + if (mentionListAnimation != null) { mentionListAnimation.cancel(); mentionListAnimation = null; @@ -1791,9 +1860,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionListView.getVisibility() == View.VISIBLE) { ViewProxy.setAlpha(mentionListView, 1.0f); return; - } - if (allowStickersPanel) { - mentionListView.setVisibility(View.VISIBLE); + } else { + mentionLayoutManager.scrollToPositionWithOffset(0, 10000); + } + if (allowStickersPanel && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { + mentionListView.setVisibility(View.VISIBLE); + mentionListView.setTag(null); mentionListAnimation = new AnimatorSetProxy(); mentionListAnimation.playTogether( ObjectAnimatorProxy.ofFloat(mentionListView, "alpha", 0.0f, 1.0f) @@ -1834,15 +1906,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { mentionListView.clearAnimation(); mentionListView.setVisibility(View.GONE); - mentionListAnimation = null; - } + mentionListView.setTag(null); + mentionListAnimation = null; } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.start(); - } else { - mentionListView.clearAnimation(); - mentionListView.setVisibility(View.GONE); + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } else { + mentionListView.setTag(null); + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.GONE); + } + } + } + + @Override + public void onContextSearch(boolean searching) { + if (chatActivityEnterView != null) { + chatActivityEnterView.setCaption(mentionsAdapter.getBotCaption()); + chatActivityEnterView.showContextProgress(searching); + } + } + + @Override + public void onContextClick(TLRPC.BotInlineResult result) { + if (getParentActivity() == null || result.content_url == null) { + return; + } + if (result.type.equals("video") || result.type.equals("web_player_video")) { + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + builder.setCustomView(new WebFrameLayout(getParentActivity(), builder.create(), result.title != null ? result.title : "", result.content_url, result.content_url, result.w, result.h)); + builder.setUseFullWidth(true); + showDialog(builder.create()); + } else { + try { + Uri uri = Uri.parse(result.content_url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, getParentActivity().getPackageName()); + getParentActivity().startActivity(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); } } } @@ -1850,11 +1954,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionsAdapter.setBotInfo(botInfo); mentionsAdapter.setChatInfo(info); mentionsAdapter.setNeedUsernames(currentChat != null); + mentionsAdapter.setNeedBotContext(currentEncryptedChat == null); mentionsAdapter.setBotsCount(currentChat != null ? botsCount : 1); - - mentionListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + mentionListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { Object object = mentionsAdapter.getItem(position); int start = mentionsAdapter.getResultStartPosition(); int len = mentionsAdapter.getResultLength(); @@ -1865,18 +1969,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (object instanceof String) { if (mentionsAdapter.isBotCommands()) { - SendMessagesHelper.getInstance().sendMessage((String) object, dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); + SendMessagesHelper.getInstance().sendMessage((String) object, dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin(), null, null); chatActivityEnterView.setFieldText(""); } else { chatActivityEnterView.replaceWithText(start, len, object + " "); } + } else if (object instanceof TLRPC.BotInlineResult) { + String text = chatActivityEnterView.getFieldText(); + if (text == null) { + return; + } + TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) object; + HashMap params = new HashMap<>(); + params.put("id", result.id); + params.put("query_id", "" + result.query_id); + params.put("bot", "" + mentionsAdapter.getContextBotId()); + mentionsAdapter.addRecentBot(); + SendMessagesHelper.prepareSendingBotContextResult(result, params, dialog_id, replyingMessageObject, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); + chatActivityEnterView.setFieldText(""); + showReplyPanel(false, null, null, null, false, true); } } - }); + }); - mentionListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { - @Override - public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + mentionListView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { + @Override + public boolean onItemClick(View view, int position) { if (!mentionsAdapter.isLongClickEnabled()) { return false; } @@ -1898,6 +2016,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } }); + + mentionListView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int firstVisibleItem = mentionLayoutManager.findFirstVisibleItemPosition(); + int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : firstVisibleItem; + if (visibleItemCount > 0 && firstVisibleItem > mentionsAdapter.getItemCount() - 5) { + mentionsAdapter.searchForContextBotForNextOffset(); + } + } + }); } pagedownButton = new ImageView(context); @@ -2010,15 +2139,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanel.clearAnimation(); stickersPanel.setVisibility(View.VISIBLE); } - if (mentionListView != null && mentionListView.getVisibility() == View.INVISIBLE) { + if (mentionListView != null && mentionListView.getVisibility() == View.INVISIBLE && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { mentionListView.clearAnimation(); mentionListView.setVisibility(View.VISIBLE); - } + mentionListView.setTag(null); + } //plus - if (mentionListView != null) { + if (mentionListView != null && !mentionsAdapter.isBotContext()) { try{ int y = AndroidUtilities.displaySize.y / size >= 1 ? AndroidUtilities.displaySize.y / size : 1; - int height = AndroidUtilities.dp(37 * Math.min(10/y, mentionsAdapter.getCount()));//puede haber java.lang.ArithmeticException: divide by zero + int height = AndroidUtilities.dp(37 * Math.min(10/y, mentionsAdapter.getItemCount()));//puede haber java.lang.ArithmeticException: divide by zero FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) mentionListView.getLayoutParams(); if(height != layoutParams3.height) { layoutParams3.height = height; @@ -2029,9 +2159,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FileLog.e("tmessages", e); } } - } + } + allowContextBotPanel = !chatActivityEnterView.isPopupShowing(); + checkContextBotPanel(); updateMessagesVisisblePart(); } + + @Override + public void onStickersTab(boolean opened) { + if (emojiButtonRed != null) { + emojiButtonRed.setVisibility(View.GONE); + } + allowContextBotPanelSecond = !opened; + checkContextBotPanel(); + } }); FrameLayout replyLayout = new FrameLayout(context); @@ -2103,8 +2244,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); } stickersPanel.addView(stickersListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 78)); - if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 23) { - chatActivityEnterView.setAllowStickers(true); + if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 23) { + chatActivityEnterView.setAllowStickersAndGifs(true, currentEncryptedChat == null); if (stickersAdapter != null) { stickersAdapter.onDestroy(); } @@ -2189,59 +2330,59 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (getParentActivity() == null) { return; } - AlertDialog.Builder builder = null; + AlertDialog.Builder builder = null; if (currentUser != null && userBlocked) { - if (currentUser.bot) { - String botUserLast = botUser; - botUser = null; - MessagesController.getInstance().unblockUser(currentUser.id); - if (botUserLast != null && botUserLast.length() != 0) { - MessagesController.getInstance().sendBotStart(currentUser, botUserLast); - } else { - SendMessagesHelper.getInstance().sendMessage("/start", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); - } - } else { - builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - MessagesController.getInstance().unblockUser(currentUser.id); + if (currentUser.bot) { + String botUserLast = botUser; + botUser = null; + MessagesController.getInstance().unblockUser(currentUser.id); + if (botUserLast != null && botUserLast.length() != 0) { + MessagesController.getInstance().sendBotStart(currentUser, botUserLast); + } else { + SendMessagesHelper.getInstance().sendMessage("/start", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin(), null, null); } - }); - } - } else if (currentUser != null && currentUser.bot && botUser != null) { - if (botUser.length() != 0) { - MessagesController.getInstance().sendBotStart(currentUser, botUser); - } else { - SendMessagesHelper.getInstance().sendMessage("/start", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); - } - botUser = null; - updateBottomOverlay(); - } else { - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && !(currentChat instanceof TLRPC.TL_channelForbidden)) { - if (ChatObject.isNotInChat(currentChat)) { - MessagesController.getInstance().addUserToChat(currentChat.id, UserConfig.getCurrentUser(), null, 0, null, null); } else { - toggleMute(true); + builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + MessagesController.getInstance().unblockUser(currentUser.id); + } + }); } - } else { - builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.getString("AreYouSureDeleteThisChat", R.string.AreYouSureDeleteThisChat)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - MessagesController.getInstance().deleteDialog(dialog_id, false); - finishFragment(); + } else if (currentUser != null && currentUser.bot && botUser != null) { + if (botUser.length() != 0) { + MessagesController.getInstance().sendBotStart(currentUser, botUser); + } else { + SendMessagesHelper.getInstance().sendMessage("/start", dialog_id, null, null, false, chatActivityEnterView == null || chatActivityEnterView.asAdmin(), null, null); + } + botUser = null; + updateBottomOverlay(); + } else { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && !(currentChat instanceof TLRPC.TL_channelForbidden)) { + if (ChatObject.isNotInChat(currentChat)) { + MessagesController.getInstance().addUserToChat(currentChat.id, UserConfig.getCurrentUser(), null, 0, null, null); + } else { + toggleMute(true); } - }); + } else { + builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage(LocaleController.getString("AreYouSureDeleteThisChat", R.string.AreYouSureDeleteThisChat)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + MessagesController.getInstance().deleteDialog(dialog_id, 0); + finishFragment(); + } + }); + } + } + if (builder != null) { + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); } - } - if (builder != null) { - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - } } }); @@ -2265,14 +2406,180 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.addView(playerView = new PlayerView(context, this), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); } - updateContactStatus(); - updateBottomOverlay(); - updateSecretStatus(); + dateTv = new TextView(context); + dateTv.setVisibility(View.GONE); + dateTv.setPadding(AndroidUtilities.dp(5), 0, AndroidUtilities.dp(5), 0); + dateTv.setTextSize(themePrefs.getInt("chatDateSize", 16)); + GradientDrawable shape = new GradientDrawable(); + shape.setCornerRadius(AndroidUtilities.dp(4)); + shape.setColor(themePrefs.getInt("chatDateBubbleColor", 0xdd777777)); + dateTv.setBackgroundDrawable(shape); + dateTv.setTextColor(themePrefs.getInt("chatDateColor", 0xffffffff)); + contentView.addView(dateTv, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER, 0, 2, 0, 0)); + + updateContactStatus(); + updateBottomOverlay(); + updateSecretStatus(); updateSpamView(); return fragmentView; } + private void updateDateToast(){ + if (chatListView == null) { + return; + } + + View view = chatListView.getChildAt(0); + if (view instanceof ChatBaseCell) { + ChatBaseCell messageCell = (ChatBaseCell) view; + String d = LocaleController.formatDateChat(messageCell.getMessageObject().messageOwner.date); + if(d.length() > 1){ + dateTv.setVisibility(View.VISIBLE); + dateTv.setText(d); + } + } + } + + private void hideDateTv(){ + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + + @Override + public void run() { + dateTv.setVisibility(View.GONE); + } + + }, 1500); + } + + private void showGifHint() { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + if (preferences.getBoolean("gifhint", false)) { + return; + } + preferences.edit().putBoolean("gifhint", true).commit(); + + if (getParentActivity() == null || fragmentView == null || gifHintTextView != null) { + return; + } + if (!allowContextBotPanelSecond) { + if (chatActivityEnterView != null) { + chatActivityEnterView.setOpenGifsTabFirst(); + } + return; + } + SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; + int index = frameLayout.indexOfChild(chatActivityEnterView); + if (index == -1) { + return; + } + chatActivityEnterView.setOpenGifsTabFirst(); + emojiButtonRed = new View(getParentActivity()); + emojiButtonRed.setBackgroundResource(R.drawable.redcircle); + frameLayout.addView(emojiButtonRed, index + 1, LayoutHelper.createFrame(10, 10, Gravity.BOTTOM | Gravity.LEFT, 30, 0, 0, 27)); + + gifHintTextView = new TextView(getParentActivity()); + gifHintTextView.setBackgroundResource(R.drawable.tooltip); + gifHintTextView.setTextColor(0xffffffff); + gifHintTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + gifHintTextView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); + gifHintTextView.setText(LocaleController.getString("TapHereGifs", R.string.TapHereGifs)); + gifHintTextView.setGravity(Gravity.CENTER_VERTICAL); + frameLayout.addView(gifHintTextView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.LEFT | Gravity.BOTTOM, 5, 0, 0, 3)); + + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(gifHintTextView, "alpha", 0.0f, 1.0f), + ObjectAnimatorProxy.ofFloat(emojiButtonRed, "alpha", 0.0f, 1.0f) + ); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (gifHintTextView == null) { + return; + } + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(gifHintTextView, "alpha", 0.0f) + ); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (gifHintTextView != null) { + gifHintTextView.clearAnimation(); + gifHintTextView.setVisibility(View.GONE); + } + } + }); + animatorSetProxy.setDuration(300); + animatorSetProxy.start(); + } + }, 2000); + } + }); + animatorSetProxy.setDuration(300); + animatorSetProxy.start(); + } + + private void checkContextBotPanel() { + if (allowStickersPanel && mentionsAdapter != null && mentionsAdapter.isBotContext()) { + if (!allowContextBotPanel && !allowContextBotPanelSecond) { + if (mentionListView.getVisibility() == View.VISIBLE && mentionListView.getTag() == null) { + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; + } + + mentionListView.setTag(1); + mentionListAnimation = new AnimatorSetProxy(); + mentionListAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(mentionListView, "alpha", 0.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.INVISIBLE); + mentionListAnimation = null; + } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } + } else { + if (mentionListView.getVisibility() == View.INVISIBLE || mentionListView.getTag() != null) { + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; + } + mentionListView.setTag(null); + mentionListView.setVisibility(View.VISIBLE); + mentionListAnimation = new AnimatorSetProxy(); + mentionListAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(mentionListView, "alpha", 0.0f, 1.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListView.clearAnimation(); + mentionListAnimation = null; + } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } + } + } + } + private void openAddMember() { Bundle args = new Bundle(); args.putBoolean("onlyUsers", true); @@ -2304,7 +2611,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void checkScrollForLoad() { - if (chatLayoutManager == null) { + if (chatLayoutManager == null || paused) { return; } int firstVisibleItem = chatLayoutManager.findFirstVisibleItemPosition(); @@ -2445,7 +2752,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); return; } - PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(false, ChatActivity.this); + PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(false, currentEncryptedChat == null, ChatActivity.this); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override public void didSelectPhotos(ArrayList photos, ArrayList captions, ArrayList webPhotos) { @@ -2890,11 +3197,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedSticker", messageObjects.size())); } else if (type == 8 || type == 9) { if (messageObjects.size() == 1) { + if (type == 8) { + replyObjectTextView.setText(LocaleController.getString("AttachGif", R.string.AttachGif)); + } else { String name; if ((name = FileLoader.getDocumentFileName(messageObjects.get(0).messageOwner.media.document)).length() != 0) { replyObjectTextView.setText(name); } messageObject = messageObjects.get(0); + } } else { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedFile", messageObjects.size())); } @@ -3448,6 +3759,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedMessagesIds[0].isEmpty() && selectedMessagesIds[1].isEmpty()) { actionBar.hideActionMode(); } else { + try{ + actionBar.createActionMode().getItem(forward).setVisibility(messageObject.messageOwner.media != null && messageObject.messageOwner.media.caption != null && messageObject.messageOwner.media.caption.length() > 0 ? View.GONE : View.VISIBLE ); + } catch (Exception e) { + FileLog.e("tmessages", e); + } int copyVisible = actionBar.createActionMode().getItem(copy).getVisibility(); actionBar.createActionMode().getItem(copy).setVisibility(selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); int newCopyVisible = actionBar.createActionMode().getItem(copy).getVisibility(); @@ -4293,8 +4609,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not endReached[loadIndex] = true; } cacheEndReached[loadIndex] = true; - } else { - endReached[loadIndex] = true; + } else if (load_type != 2) { + endReached[loadIndex] = true;// TODO if < 7 from unread } } loading = false; @@ -4396,7 +4712,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView != null) { chatListView.setEmptyView(null); } - emptyViewContainer.setVisibility(View.INVISIBLE); + if (emptyViewContainer != null) { + emptyViewContainer.setVisibility(View.INVISIBLE); + } } else { if (progressView != null) { progressView.setVisibility(View.INVISIBLE); @@ -4816,6 +5134,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messages.remove(index); messagesDict[loadIndex].remove(ids); ArrayList dayArr = messagesByDays.get(obj.dateKey); + if (dayArr != null) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); @@ -4827,6 +5146,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + } if (messages.isEmpty()) { if (!endReached[0] && !loading) { if (progressView != null) { @@ -5124,15 +5444,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (botButtons != null) { botButtons = null; + if (chatActivityEnterView != null) { chatActivityEnterView.setButtons(null, false); } + } if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { botUser = ""; updateBottomOverlay(); } if ((Boolean) args[1]) { - progressView.setVisibility(chatAdapter.botInfoRow == -1 ? View.VISIBLE : View.INVISIBLE); - chatListView.setEmptyView(null); + if (chatAdapter != null) { + progressView.setVisibility(chatAdapter.botInfoRow == -1 ? View.VISIBLE : View.INVISIBLE); + chatListView.setEmptyView(null); + } for (int a = 0; a < 2; a++) { endReached[a] = false; cacheEndReached[a] = false; @@ -5440,7 +5764,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onDialogDismiss(Dialog dialog) { if (closeChatDialog != null && dialog == closeChatDialog) { - MessagesController.getInstance().deleteDialog(dialog_id, false); + MessagesController.getInstance().deleteDialog(dialog_id, 0); finishFragment(); } } @@ -5668,6 +5992,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not readWhenResume = false; MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).getId(), readWithMid, readWithDate, true, false); } + checkScrollForLoad(); if (wasPaused) { wasPaused = false; if (chatAdapter != null) { @@ -5825,7 +6150,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.onPause(); String text = chatActivityEnterView.getFieldText(); - if (text != null) { + if (text != null && !text.equals("@gif ")) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString("dialog_" + dialog_id, text); @@ -6093,8 +6418,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (type == 3) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); + if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { + items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + options.add(11); + } } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (MessageObject.isNewGifDocument(selectedObject.messageOwner.media.document)) { + items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + options.add(11); + } items.add(selectedObject.isMusic() ? LocaleController.getString("SaveToMusic", R.string.SaveToMusic) : LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); @@ -6104,12 +6437,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(4); } } else if (type == 5) { - items.add(LocaleController.getString("ApplyTheme", R.string.ApplyTheme)); + items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); + items.add(LocaleController.getString("ApplyTheme", R.string.ApplyTheme)); + options.add(55); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(4); } else if (type == 6) { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(7); items.add(selectedObject.isMusic() ? LocaleController.getString("SaveToMusic", R.string.SaveToMusic) : LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); @@ -6123,7 +6458,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(22); //items.add(LocaleController.getString("Forward", R.string.Forward)); if(selectedObject.messageOwner.media != null && selectedObject.messageOwner.media.caption != null && selectedObject.messageOwner.media.caption.length() > 0){ - //with caption quote doesn't appear + }else { items.add(LocaleController.getString("ForwardNoQuote", R.string.ForwardNoQuote)); options.add(2); @@ -6146,9 +6481,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); } - } else if (type == 5) { - items.add(LocaleController.getString("ApplyTheme", R.string.ApplyTheme)); + } else if (type == 5) { + items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); + items.add(LocaleController.getString("ApplyTheme", R.string.ApplyTheme)); + options.add(55); } else if (type == 7) { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(9); @@ -6173,7 +6510,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); builder.setTitle(LocaleController.getString("Message", R.string.Message)); - if(!AndroidUtilities.getBoolMain("disableMessageClick") || type != 3){ + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + if(!plusPreferences.getBoolean("disableMessageClick", false) || type != 3){ showDialog(builder.create()); } } @@ -6280,7 +6619,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); } - } /*else if (option == 5) { + } else if (option == 5) { File locFile = null; if (selectedObject.messageOwner.attachPath != null && selectedObject.messageOwner.attachPath.length() != 0) { File f = new File(selectedObject.messageOwner.attachPath); @@ -6308,7 +6647,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); } } - }*/else if (option == 5) { //Apply theme + } else if (option == 55) { //Apply theme File locFile = null; if (selectedObject.messageOwner.attachPath != null && selectedObject.messageOwner.attachPath.length() != 0) { File f = new File(selectedObject.messageOwner.attachPath); @@ -6395,6 +6734,34 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), selectedObject.isMusic() ? 3 : 2, fileName); + } else if (option == 11) { + MediaController.SearchImage searchImage = new MediaController.SearchImage(); + searchImage.type = 2; + if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { + searchImage.document = selectedObject.messageOwner.media.webpage.document; + } else { + searchImage.document = selectedObject.messageOwner.media.document; + } + searchImage.date = (int) (System.currentTimeMillis() / 1000); + searchImage.id = "" + searchImage.document.id; + + ArrayList arrayList = new ArrayList<>(); + arrayList.add(searchImage); + MessagesStorage.getInstance().putWebRecent(arrayList); + TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif(); + req.id = new TLRPC.TL_inputDocument(); + req.id.id = searchImage.document.id; + req.id.access_hash = searchImage.document.access_hash; + req.unsave = false; + ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + + } + }); + showGifHint(); + + chatActivityEnterView.addRecentGif(searchImage); } selectedObject = null; } @@ -6799,12 +7166,186 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not processRowSelect(cell); return; } - if (user != null && user.id != UserConfig.getClientUserId()) { + //if (user != null && user.id != UserConfig.getClientUserId()) { + /*if (user != null) { Bundle args = new Bundle(); args.putInt("user_id", user.id); - ProfileActivity fragment = new ProfileActivity(args); - fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id); - presentFragment(fragment); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id); + presentFragment(fragment); + }*/ + // + if (user != null) { + final boolean isChat = (int) dialog_id < 0 && (int) (dialog_id >> 32) != 1; + if(isChat && user.id != UserConfig.getClientUserId()) { + final TLRPC.User usr = user; + String name = UserObject.getFirstName(user); + boolean allowKick = false; + boolean allowSetAdmin = false; + boolean removeAdmin = false; + int index = -1; + TLRPC.ChatParticipant chatParticipant = null; + //ArrayList participants = new ArrayList<>(); + //TLRPC.ChannelParticipant channelParticipant = null; + if (user.id != UserConfig.getClientUserId() && info != null && info.participants != null) { + if (currentChat.megagroup) { + for (int a = 0; a < info.participants.participants.size(); a++) { + TLRPC.ChatParticipant p = info.participants.participants.get(a); + if (p instanceof TLRPC.TL_chatChannelParticipant) { + TLRPC.ChannelParticipant channelParticipant = ((TLRPC.TL_chatChannelParticipant) p).channelParticipant; + //participants.add(channelParticipant); + if (channelParticipant.user_id == user.id) { + index = a; + if (currentChat.creator || currentChat.editor && !(channelParticipant instanceof TLRPC.TL_channelParticipantEditor || channelParticipant instanceof TLRPC.TL_channelParticipantCreator) || channelParticipant.inviter_id == UserConfig.getClientUserId()) { + allowKick = true; + } + allowSetAdmin = currentChat.creator && !(channelParticipant instanceof TLRPC.TL_channelParticipantEditor) && !user.bot; + removeAdmin = currentChat.creator && channelParticipant instanceof TLRPC.TL_channelParticipantEditor && !user.bot; + //Log.e("ChatActivity","allowSetAdmin " + allowSetAdmin + " removeAdmin " + removeAdmin + " " + (channelParticipant instanceof TLRPC.TL_channelParticipantEditor)); + break; + } + } + } + } else { + for (int a = 0; a < info.participants.participants.size(); a++) { + TLRPC.ChatParticipant p = info.participants.participants.get(a); + if (p.user_id == user.id) { + chatParticipant = p; + index = a; + if (currentChat.creator || currentChat.admin && currentChat.admins_enabled && !(p instanceof TLRPC.TL_chatParticipantAdmin || p instanceof TLRPC.TL_chatParticipantCreator) || p.inviter_id == UserConfig.getClientUserId() ) { + allowKick = true; + } + allowSetAdmin = currentChat.creator && currentChat.admins_enabled && !(p instanceof TLRPC.TL_chatParticipantAdmin); + removeAdmin = currentChat.creator && currentChat.admins_enabled && p instanceof TLRPC.TL_chatParticipantAdmin; + break; + } + } + } + } + + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(name); + final int finalIndex = index; + final TLRPC.ChatParticipant finalChatParticipant = chatParticipant; + //final ArrayList finalParticipants = participants; + //final TLRPC.ChannelParticipant finalChannelParticipant = channelParticipant; + final boolean finalRemoveAdmin = removeAdmin; + if (allowSetAdmin || removeAdmin) { + builder.setItems(new CharSequence[]{LocaleController.getString("ShowProfile", R.string.ShowProfile), LocaleController.getString("KickFromGroup", R.string.KickFromGroup), removeAdmin ? LocaleController.getString("RemoveUserAdmin", R.string.RemoveUserAdmin) : LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin)}, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (i == 2) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage((finalRemoveAdmin ? LocaleController.getString("RemoveUserAdmin", R.string.RemoveUserAdmin) : LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin)) + '\n' +LocaleController.getString("AreYouSure", R.string.AreYouSure)); + builder.setTitle(UserObject.getFirstName(usr)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if(currentChat.megagroup){ //SuperGroup + + TLRPC.TL_channels_editAdmin req = new TLRPC.TL_channels_editAdmin(); + req.channel = MessagesController.getInputChannel(chat_id); + req.user_id = MessagesController.getInputUser(usr.id); + req.role = finalRemoveAdmin ? new TLRPC.TL_channelRoleEmpty() : new TLRPC.TL_channelRoleEditor(); + ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(TLObject response, final TLRPC.TL_error error) { + if (error == null) { + MessagesController.getInstance().processUpdates((TLRPC.Updates) response, false); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().loadFullChat(chat_id, 0, true); + getChannelParticipants(); + } + }, 1000); + } else { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + AlertsCreator.showAddUserAlert(error.text, ChatActivity.this, false); + } + }); + } + } + }); + } else { // Group + //index = info.participants.participants.indexOf(finalChatParticipant); + if (finalIndex != -1 && !(finalChatParticipant instanceof TLRPC.TL_chatParticipantCreator)) { + TLRPC.ChatParticipant newParticipant; + if (finalChatParticipant instanceof TLRPC.TL_chatParticipant) { + newParticipant = new TLRPC.TL_chatParticipantAdmin(); + newParticipant.user_id = finalChatParticipant.user_id; + newParticipant.date = finalChatParticipant.date; + newParticipant.inviter_id = finalChatParticipant.inviter_id; + } else { + newParticipant = new TLRPC.TL_chatParticipant(); + newParticipant.user_id = finalChatParticipant.user_id; + newParticipant.date = finalChatParticipant.date; + newParticipant.inviter_id = finalChatParticipant.inviter_id; + } + info.participants.participants.set(finalIndex, newParticipant); + if (currentChat != null && currentChat.admins_enabled) { + MessagesController.getInstance().toggleUserAdmin(chat_id, usr.id, !finalRemoveAdmin/*!(finalChatParticipant instanceof TLRPC.TL_chatParticipant)*/); + } + } + } + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + } else if (i == 1) { + kickUser(usr); + } else if (i == 0) { //Profile + try { + Bundle args = new Bundle(); + args.putInt("user_id", usr.id); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == usr.id); + presentFragment(fragment); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + } + ); + showDialog(builder.create()); + } else if(allowKick){ + builder.setItems(new CharSequence[]{LocaleController.getString("ShowProfile", R.string.ShowProfile), LocaleController.getString("KickFromGroup", R.string.KickFromGroup)}, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (i == 1) { //Kick + kickUser(usr); + } else if (i == 0) { //Profile + try { + Bundle args = new Bundle(); + args.putInt("user_id", usr.id); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == usr.id); + presentFragment(fragment); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + } + ); + showDialog(builder.create()); + } else{ + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id); + presentFragment(fragment); + } + } else{ + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id); + presentFragment(fragment); + } } } @@ -6885,6 +7426,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override + public void didPressedViaBot(ChatBaseCell cell, TLRPC.User user) { + if (chatActivityEnterView != null && user != null && user.username != null && user.username.length() > 0) { + chatActivityEnterView.setFieldText("@" + user.username + " "); + chatActivityEnterView.openKeyboard(); + } + } + + @Override public void didClickedImage(ChatBaseCell cell) { MessageObject message = cell.getMessageObject(); if (message.isSendError()) { @@ -6968,11 +7517,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - } + } }); - if (view instanceof ChatMediaCell) { - ((ChatMediaCell) view).setAllowedToSetPhoto(openAnimationEnded); - ((ChatMediaCell) view).setMediaDelegate(new ChatMediaCell.ChatMediaCellDelegate() { + if (view instanceof ChatMediaCell) { + ((ChatMediaCell) view).setAllowedToSetPhoto(openAnimationEnded); + ((ChatMediaCell) view).setMediaDelegate(new ChatMediaCell.ChatMediaCellDelegate() { @Override public void didPressedOther(ChatMediaCell cell) { createMenu(cell, true); @@ -7081,6 +7630,68 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return new Holder(view); } + private void getChannelParticipants() { + final TLRPC.TL_channels_getParticipants req = new TLRPC.TL_channels_getParticipants(); + req.channel = MessagesController.getInputChannel(chat_id); + req.filter = new TLRPC.TL_channelParticipantsRecent(); + req.offset = 0; + req.limit = 33; + int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (error == null) { + TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; + MessagesController.getInstance().putUsers(res.users, false); + if (res.participants.size() == 33) { + res.participants.remove(32); + } + if (req.offset == 0) { + MessagesStorage.getInstance().putUsersAndChats(res.users, null, true, true); + MessagesStorage.getInstance().updateChannelUsers(chat_id, res.participants); + } + } + } + }, Build.VERSION.SDK_INT >= 11 ? 300 : 0); + } + }); + ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid); + } + + private void kickUser(final TLRPC.User user) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setMessage(LocaleController.getString("KickFromGroup", R.string.KickFromGroup) + '\n' +LocaleController.getString("AreYouSure", R.string.AreYouSure)); + builder.setTitle(UserObject.getFirstName(user)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + try{ + MessagesController.getInstance().deleteUserFromChat(chat_id, user, info); + boolean changed = false; + if (info != null && info.participants != null) { + for (int a = 0; a < info.participants.participants.size(); a++) { + TLRPC.ChatParticipant p = info.participants.participants.get(a); + if (p.user_id == user.id) { + info.participants.participants.remove(a); + changed = true; + break; + } + } + } + if (changed) { + chatAdapter.notifyDataSetChanged(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + } + @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position == botInfoRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index aac7c83b..489b3158 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java index d740dfa5..3612dab3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -82,7 +82,7 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg return; } } - PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(true, null); + PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(true, false, null); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override public void didSelectPhotos(ArrayList photos, ArrayList captions, ArrayList webPhotos) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index dc1e5f8a..8664e8b1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 3a5f5079..77cfe429 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -3,12 +3,13 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; @@ -22,6 +23,10 @@ import android.media.AudioManager; import android.os.Build; import android.os.PowerManager; import android.text.Editable; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.ImageSpan; import android.util.TypedValue; @@ -61,6 +66,7 @@ import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.ApplicationLoader; +import org.telegram.ui.StickersActivity; import java.util.Locale; @@ -73,9 +79,90 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat void onAttachButtonHidden(); void onAttachButtonShow(); void onWindowSizeChanged(int size); + void onStickersTab(boolean opened); } - private EditText messageEditText; + private class EditTextCaption extends EditText { + + private String caption; + private StaticLayout captionLayout; + private int userNameLength; + private int xOffset; + private int yOffset; + + public EditTextCaption(Context context) { + super(context); + } + + public void setCaption(String value) { + if ((caption == null || caption.length() == 0) && (value == null || value.length() == 0) || caption != null && value != null && caption.equals(value)) { + return; + } + caption = value; + if (caption != null) { + caption = caption.replace('\n', ' '); + } + requestLayout(); + } + + @SuppressLint("DrawAllocation") + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + captionLayout = null; + + if (caption != null && caption.length() > 0) { + CharSequence text = getText(); + if (text.length() > 1 && text.charAt(0) == '@') { + int index = TextUtils.indexOf(text, ' '); + if (index != -1) { + TextPaint paint = getPaint(); + CharSequence str = text.subSequence(0, index + 1); + int size = (int) Math.ceil(paint.measureText(text, 0, index + 1)); + int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); + userNameLength = str.length(); + CharSequence captionFinal = TextUtils.ellipsize(caption, paint, width - size, TextUtils.TruncateAt.END); + xOffset = size; + try { + captionLayout = new StaticLayout(captionFinal, getPaint(), width - size, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (captionLayout.getLineCount() > 0) { + xOffset += -captionLayout.getLineLeft(0); + } + yOffset = (getMeasuredHeight() - captionLayout.getLineBottom(0)) / 2 + AndroidUtilities.dp(0.5f); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (captionLayout != null && userNameLength == length()) { + Paint paint = getPaint(); + int oldColor = getPaint().getColor(); + paint.setColor(0xffb2b2b2); + canvas.save(); + canvas.translate(xOffset, yOffset); + captionLayout.draw(canvas); + canvas.restore(); + paint.setColor(oldColor); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { + showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); + openKeyboardInternal(); + } + return super.onTouchEvent(event); + } + } + + private EditTextCaption messageEditText; private ImageView sendButton; private ImageView emojiButton; private EmojiView emojiView; @@ -93,6 +180,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private BotKeyboardView botKeyboardView; private ImageView asAdminButton; private RecordCircle recordCircle; + private ContextProgressView contextProgressView; private int currentPopupContentType = -1; @@ -126,6 +214,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private boolean recordingAudio; private boolean forceShowSendButton; private boolean allowStickers; + private boolean allowGifs; private int lastSizeChangeValue1; private boolean lastSizeChangeValue2; @@ -326,20 +415,12 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat showPopup(1, 0); } else { openKeyboardInternal(); - } + removeGifFromInputField(); + } } }); - messageEditText = new EditText(context) { - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { - showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); - openKeyboardInternal(); - } - return super.onTouchEvent(event); - } - }; + messageEditText = new EditTextCaption(context); updateFieldHint(); messageEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); messageEditText.setInputType(messageEditText.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); @@ -366,6 +447,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); } showPopup(0, 0); + removeGifFromInputField(); } return true; } else if (i == KeyEvent.KEYCODE_ENTER && (ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN) { @@ -459,6 +541,10 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat }); if (isChat) { + contextProgressView = new ContextProgressView(context); + contextProgressView.setVisibility(INVISIBLE); + frameLayout.addView(contextProgressView, LayoutHelper.createFrame(38, 48, Gravity.BOTTOM | Gravity.RIGHT)); + attachButton = new LinearLayout(context); attachButton.setOrientation(LinearLayout.HORIZONTAL); attachButton.setEnabled(false); @@ -672,7 +758,6 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat keyboardHeightLand = sharedPreferences.getInt("kbd_height_land3", AndroidUtilities.dp(200)); checkSendButton(false); - updateTheme(); } @@ -711,9 +796,25 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat setBackgroundDrawable(gd); textFieldContainer.setBackgroundDrawable(gd); } - } + public void showContextProgress(boolean show) { + if (contextProgressView == null) { + return; + } + contextProgressView.setVisibility(show ? VISIBLE : INVISIBLE); + try { + messageEditText.setPadding(0, AndroidUtilities.dp(11), show ? AndroidUtilities.dp(38) : 0, AndroidUtilities.dp(12)); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + public void setCaption(String caption) { + if (messageEditText != null) { + messageEditText.setCaption(caption); + } + } public void addTopView(View view, int height) { if (view == null) { @@ -741,8 +842,15 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat checkSendButton(animated); } - public void setAllowStickers(boolean value) { + public void setAllowStickersAndGifs(boolean value, boolean value2) { allowStickers = value; + allowGifs = value2; + } + + public void setOpenGifsTabFirst() { + createEmojiView(); + emojiView.loadGifRecent(); + emojiView.switchToGifRecent(); } public boolean asAdmin() { @@ -999,7 +1107,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat int count = (int) Math.ceil(text.length() / 4096.0f); for (int a = 0; a < count; a++) { String mess = text.substring(a * 4096, Math.min((a + 1) * 4096, text.length())); - SendMessagesHelper.getInstance().sendMessage(mess, dialog_id, replyingMessageObject, messageWebPage, messageWebPageSearch, asAdmin()); + SendMessagesHelper.getInstance().sendMessage(mess, dialog_id, replyingMessageObject, messageWebPage, messageWebPageSearch, asAdmin(), null, null); } return true; } @@ -1323,9 +1431,9 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } else { TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? MessagesController.getInstance().getUser(messageObject.messageOwner.from_id) : null; if ((botCount != 1 || username) && user != null && user.bot && !command.contains("@")) { - SendMessagesHelper.getInstance().sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, null, null, false, asAdmin()); + SendMessagesHelper.getInstance().sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, null, null, false, asAdmin(), null, null); } else { - SendMessagesHelper.getInstance().sendMessage(command, dialog_id, null, null, false, asAdmin()); + SendMessagesHelper.getInstance().sendMessage(command, dialog_id, null, null, false, asAdmin(), null, null); } } } @@ -1480,7 +1588,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat @Override public void didPressedButton(CharSequence text) { MessageObject object = replyingMessageObject != null ? replyingMessageObject : ((int) dialog_id < 0 ? botButtonsMessageObject : null); - SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, object, null, false, asAdmin()); + SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, object, null, false, asAdmin(), null, null); if (replyingMessageObject != null) { openKeyboardInternal(); setButtons(botMessageObject, false); @@ -1532,6 +1640,84 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat return view == recordCircle; } + private void createEmojiView() { + if (emojiView != null) { + return; + } + emojiView = new EmojiView(allowStickers, allowGifs, parentActivity); + emojiView.setVisibility(GONE); + emojiView.setListener(new EmojiView.Listener() { + public boolean onBackspace() { + if (messageEditText.length() == 0) { + return false; + } + messageEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + return true; + } + + public void onEmojiSelected(String symbol) { + int i = messageEditText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + innerTextChange = 2; + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + messageEditText.setSelection(j, j); + } catch (Exception e) { + FileLog.e("tmessages", e); + } finally { + innerTextChange = 0; + } + } + + public void onStickerSelected(TLRPC.Document sticker) { + SendMessagesHelper.getInstance().sendSticker(sticker, dialog_id, replyingMessageObject, asAdmin()); + if (delegate != null) { + delegate.onMessageSend(null); + } + } + + @Override + public void onStickersSettingsClick() { + if (parentFragment != null) { + parentFragment.presentFragment(new StickersActivity()); + } + } + + @Override + public void onGifSelected(TLRPC.Document gif) { + SendMessagesHelper.getInstance().sendMessage((TLRPC.TL_document) gif, null, dialog_id, replyingMessageObject, asAdmin(), null); + if (delegate != null) { + delegate.onMessageSend(null); + } + } + + @Override + public void onGifTab(boolean opened) { + if (!AndroidUtilities.usingHardwareInput) { + if (opened) { + if (messageEditText.length() == 0) { + messageEditText.setText("@gif "); + messageEditText.setSelection(messageEditText.length()); + } + } else if (messageEditText.getText().toString().equals("@gif ")) { + messageEditText.setText(""); + } + } + } + + @Override + public void onStickersTab(boolean opened) { + delegate.onStickersTab(opened); + } + }); + emojiView.setVisibility(GONE); + sizeNotifierLayout.addView(emojiView); + } + private void showPopup(int show, int contentType) { SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); int color = themePrefs.getInt("chatEditTextIconsColor", 0xffadadad); @@ -1540,43 +1726,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (parentActivity == null) { return; } - emojiView = new EmojiView(allowStickers, parentActivity); - emojiView.setVisibility(GONE); - emojiView.setListener(new EmojiView.Listener() { - public boolean onBackspace() { - if (messageEditText.length() == 0) { - return false; - } - messageEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); - return true; - } - - public void onEmojiSelected(String symbol) { - int i = messageEditText.getSelectionEnd(); - if (i < 0) { - i = 0; - } - try { - innerTextChange = 2; - CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); - messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); - int j = i + localCharSequence.length(); - messageEditText.setSelection(j, j); - } catch (Exception e) { - FileLog.e("tmessages", e); - } finally { - innerTextChange = 0; - } - } - - public void onStickerSelected(TLRPC.Document sticker) { - SendMessagesHelper.getInstance().sendSticker(sticker, dialog_id, replyingMessageObject, asAdmin()); - if (delegate != null) { - delegate.onMessageSend(null); - } - } - }); - sizeNotifierLayout.addView(emojiView); + createEmojiView(); } View currentView = null; @@ -1667,6 +1817,15 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); } showPopup(0, 0); + removeGifFromInputField(); + } + } + + private void removeGifFromInputField() { + if (!AndroidUtilities.usingHardwareInput) { + if (messageEditText.getText().toString().equals("@gif ")) { + messageEditText.setText(""); + } } } @@ -1695,6 +1854,17 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat return emojiView != null && emojiView.getVisibility() == VISIBLE || botKeyboardView != null && botKeyboardView.getVisibility() == VISIBLE; } + public boolean isKeyboardVisible() { + return keyboardVisible; + } + + public void addRecentGif(MediaController.SearchImage searchImage) { + if (emojiView == null) { + return; + } + emojiView.addRecentGif(searchImage); + } + @Override public void onSizeChanged(int height, boolean isWidthGreater) { if (height > AndroidUtilities.dp(50) && keyboardVisible) { @@ -1709,8 +1879,9 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (isPopupShowing()) { int newHeight = isWidthGreater ? keyboardHeightLand : keyboardHeight; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emoji", Activity.MODE_PRIVATE); - int pSize = preferences.getInt("emojiPopupSize", 60); + //SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emoji", Activity.MODE_PRIVATE); + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + int pSize = plusPreferences.getInt("emojiPopupSize", 60); int popupSize = AndroidUtilities.dp((pSize - 40) * 10); newHeight = popupSize < newHeight ? newHeight : popupSize; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java index 1bb73b56..cd99cc05 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index a9ddcaac..615777ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 865dcfb2..bd42e85d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -3,19 +3,21 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.database.DataSetObserver; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.RectF; import android.graphics.PorterDuff; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; @@ -45,12 +47,19 @@ import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.query.StickersQuery; import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.query.StickersQuery; +import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.RequestDelegate; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.StickerPreviewViewer; @@ -67,6 +76,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific boolean onBackspace(); void onEmojiSelected(String emoji); void onStickerSelected(TLRPC.Document sticker); + void onStickersSettingsClick(); + void onGifSelected(TLRPC.Document gif); + void onGifTab(boolean opened); + void onStickersTab(boolean opened); } private static final Field superListenerField; @@ -480,8 +493,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private ArrayList recentEmoji = new ArrayList<>(); private HashMap stickersUseHistory = new HashMap<>(); private ArrayList recentStickers = new ArrayList<>(); - private HashMap stickerSetsUseCount = new HashMap<>(); private ArrayList stickerSets = new ArrayList<>(); + private ArrayList recentImages; + private boolean loadingRecent; private int[] icons = { R.drawable.ic_emoji_recent, @@ -502,6 +516,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private LinearLayout pagerSlidingTabStripContainer; private ScrollSlidingTabStrip scrollSlidingTabStrip; private GridView stickersGridView; + private TextView stickersEmptyView; + private RecyclerListView gifsGridView; + private FlowLayoutManager flowLayoutManager; + private GifsAdapter gifsAdapter; private AdapterView.OnItemClickListener stickersOnItemClickListener; private Runnable openStickerPreviewRunnable; private StickerEmojiCell currentStickerPreviewCell; @@ -511,6 +529,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private int popupHeight; private int emojiSize; private int location[] = new int[2]; + private int stickersTabOffset; + private int recentTabBum = -2; + private int gifTabBum = -2; + private boolean switchToGifTab; private int startX; private int startY; @@ -521,16 +543,21 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private boolean backspacePressed; private boolean backspaceOnce; private boolean showStickers; + private boolean showGifs; - public EmojiView(boolean needStickers, Context context) { + private boolean loadingRecentGifs; + private long lastGifLoadTime; + + public EmojiView(boolean needStickers, boolean needGif, final Context context) { super(context); showStickers = needStickers; + showGifs = needGif; SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); int bgColor = themePrefs.getInt("chatEmojiViewBGColor", 0xfff5f6f7); int tabColor = themePrefs.getInt("chatEmojiViewTabColor", AndroidUtilities.getIntDarkerColor("themeColor", -0x15)); int lineColor = bgColor == 0xfff5f6f7 ? 0xffe2e5e7 : AndroidUtilities.setDarkColor(bgColor, 0x10); - //setOrientation(LinearLayout.VERTICAL); + for (int i = 0; i < EmojiData.dataColored.length + 1; i++) { GridView gridView = new GridView(context); if (AndroidUtilities.isTablet()) { @@ -593,6 +620,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } return false; } + + @Override + public void setVisibility(int visibility) { + if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { + super.setVisibility(GONE); + return; + } + super.setVisibility(visibility); + } }; stickersGridView.setSelector(R.drawable.transparent); stickersGridView.setColumnWidth(AndroidUtilities.dp(72)); @@ -704,15 +740,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } stickersUseHistory.put(document.id, ++count); - long id = StickersQuery.getStickerSetId(document); - if (id != -1) { - count = stickerSetsUseCount.get(id); - if (count == null) { - count = 0; - } - stickerSetsUseCount.put(id, ++count); - } - saveRecentStickers(); if (listener != null) { listener.onStickerSelected(document); @@ -724,13 +751,98 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickersWrap = new FrameLayout(context); stickersWrap.addView(stickersGridView); - - TextView textView = new TextView(context); - textView.setText(LocaleController.getString("NoStickers", R.string.NoStickers)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - textView.setTextColor(0xff888888); - stickersWrap.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - stickersGridView.setEmptyView(textView); + + if (needGif) { + gifsGridView = new RecyclerListView(context); + gifsGridView.setLayoutManager(flowLayoutManager = new FlowLayoutManager() { + + private Size size = new Size(); + + @Override + protected Size getSizeForItem(int i) { + TLRPC.Document document = recentImages.get(i).document; + size.width = document.thumb != null && document.thumb.w != 0 ? document.thumb.w : 100; + size.height = document.thumb != null && document.thumb.h != 0 ? document.thumb.h : 100; + for (int b = 0; b < document.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; + } + } + if (size.width == 0) { + size.width = 100; + } + if (size.height == 0) { + size.height = 100; + } + return size; + } + }); + if (Build.VERSION.SDK_INT >= 9) { + gifsGridView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + } + gifsGridView.setAdapter(gifsAdapter = new GifsAdapter(context)); + gifsGridView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + if (position < 0 || position >= recentImages.size() || listener == null) { + return; + } + TLRPC.Document document = recentImages.get(position).document; + listener.onStickerSelected(document); + } + }); + gifsGridView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { + @Override + public boolean onItemClick(View view, int position) { + if (position < 0 || position >= recentImages.size()) { + return false; + } + final MediaController.SearchImage searchImage = recentImages.get(position); + AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("DeleteGif", R.string.DeleteGif)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK).toUpperCase(), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + recentImages.remove(searchImage); + TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif(); + req.id = new TLRPC.TL_inputDocument(); + req.id.id = searchImage.document.id; + req.id.access_hash = searchImage.document.access_hash; + req.unsave = true; + ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + + } + }); + MessagesStorage.getInstance().removeWebRecent(searchImage); + if (gifsAdapter != null) { + gifsAdapter.notifyDataSetChanged(); + } + if (recentImages.isEmpty()) { + updateStickerTabs(); + } + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.show(); + return true; + } + }); + gifsGridView.setVisibility(GONE); + stickersWrap.addView(gifsGridView); + } + + stickersEmptyView = new TextView(context); + stickersEmptyView.setText(LocaleController.getString("NoStickers", R.string.NoStickers)); + stickersEmptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + stickersEmptyView.setTextColor(0xff888888); + stickersWrap.addView(stickersEmptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + stickersGridView.setEmptyView(stickersEmptyView); scrollSlidingTabStrip = new ScrollSlidingTabStrip(context) { @@ -808,14 +920,41 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific scrollSlidingTabStrip.setDelegate(new ScrollSlidingTabStrip.ScrollSlidingTabStripDelegate() { @Override public void onPageSelected(int page) { + if (gifsGridView != null) { + if (page == gifTabBum + 1) { + if (gifsGridView.getVisibility() != VISIBLE) { + listener.onGifTab(true); + showGifTab(); + } + } else { + if (gifsGridView.getVisibility() == VISIBLE) { + listener.onGifTab(false); + gifsGridView.setVisibility(GONE); + stickersGridView.setVisibility(VISIBLE); + stickersEmptyView.setVisibility(stickersGridAdapter.getCount() != 0 ? GONE : VISIBLE); + } + } + } if (page == 0) { pager.setCurrentItem(0); return; - } else if (page == 1 && !recentStickers.isEmpty()) { + } else { + if (page == gifTabBum + 1) { + return; + } else { + if (page == recentTabBum + 1) { views.get(6).setSelection(0); return; } - int index = page - (recentStickers.isEmpty() ? 1 : 2); + } + } + int index = page - 1 - stickersTabOffset; + if (index == stickerSets.size()) { + if (listener != null) { + listener.onStickersSettingsClick(); + } + return; + } if (index >= stickerSets.size()) { index = stickerSets.size() - 1; } @@ -831,16 +970,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - int count = view.getChildCount(); - for (int a = 0; a < count; a++) { - View child = view.getChildAt(a); - if (child.getHeight() + child.getTop() < AndroidUtilities.dp(5)) { - firstVisibleItem++; - } else { - break; - } - } - scrollSlidingTabStrip.onPageScrolled(stickersGridAdapter.getTabForPosition(firstVisibleItem) + 1, 0); + checkStickersScroll(firstVisibleItem); } }); } @@ -848,7 +978,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific //setBackgroundColor(0xfff5f6f7); setBackgroundColor(bgColor); - pager = new ViewPager(context) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { @@ -927,7 +1056,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific //SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); Drawable icon = getResources().getDrawable(R.drawable.ic_smiles_backspace); int iconColor = themePrefs.getInt("chatEmojiViewTabIconColor", 0xffa8a8a8); - icon.setColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP); + icon.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); backspaceButton.setImageDrawable(icon); //backspaceButton.setImageResource(R.drawable.ic_smiles_backspace); backspaceButton.setBackgroundResource(R.drawable.ic_emoji_backspace); @@ -999,6 +1128,33 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific loadRecents(); } + private void showGifTab() { + gifsGridView.setVisibility(VISIBLE); + stickersGridView.setVisibility(GONE); + stickersEmptyView.setVisibility(GONE); + scrollSlidingTabStrip.onPageScrolled(gifTabBum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); + } + + private void checkStickersScroll(int firstVisibleItem) { + if (stickersGridView == null) { + return; + } + if (stickersGridView.getVisibility() != VISIBLE) { + scrollSlidingTabStrip.onPageScrolled(gifTabBum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); + return; + } + int count = stickersGridView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = stickersGridView.getChildAt(a); + if (child.getHeight() + child.getTop() < AndroidUtilities.dp(5)) { + firstVisibleItem++; + } else { + break; + } + } + scrollSlidingTabStrip.onPageScrolled(stickersGridAdapter.getTabForPosition(firstVisibleItem) + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); + } + private void onPageScrolled(int position, int width, int positionOffsetPixels) { if (scrollSlidingTabStrip == null) { return; @@ -1011,8 +1167,18 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific int margin = 0; if (position == 5) { margin = -positionOffsetPixels; + if (listener != null) { + listener.onStickersTab(positionOffsetPixels != 0); + } } else if (position == 6) { margin = -width; + if (listener != null) { + listener.onStickersTab(true); + } + } else { + if (listener != null) { + listener.onStickersTab(false); + } } if (ViewProxy.getTranslationX(pagerSlidingTabStripContainer) != margin) { @@ -1103,35 +1269,18 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } editor.putString("stickers", stringBuilder.toString()); - ArrayList toRemove = null; - for (HashMap.Entry entry : stickerSetsUseCount.entrySet()) { - if (!StickersQuery.isStickerPackInstalled(entry.getKey())) { - if (toRemove == null) { - toRemove = new ArrayList<>(); - } - toRemove.add(entry.getKey()); - } - } - if (toRemove != null) { - for (int a = 0; a < toRemove.size(); a++) { - stickerSetsUseCount.remove(toRemove.get(a)); - } - } - - stringBuilder.setLength(0); - for (HashMap.Entry entry : stickerSetsUseCount.entrySet()) { - if (stringBuilder.length() != 0) { - stringBuilder.append(","); - } - stringBuilder.append(entry.getKey()); - stringBuilder.append("="); - stringBuilder.append(entry.getValue()); - } - editor.putString("sets", stringBuilder.toString()); - editor.commit(); } + public void switchToGifRecent() { + pager.setCurrentItem(6); + if (gifTabBum >= 0 && !recentImages.isEmpty()) { + scrollSlidingTabStrip.selectTab(gifTabBum + 1); + } else { + switchToGifTab = true; + } + } + private void sortEmoji() { recentEmoji.clear(); for (HashMap.Entry entry : emojiUseHistory.entrySet()) { @@ -1204,11 +1353,26 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } private void updateStickerTabs() { + recentTabBum = -2; + gifTabBum = -2; + + stickersTabOffset = 0; + int lastPosition = scrollSlidingTabStrip.getCurrentPosition(); scrollSlidingTabStrip.removeTabs(); - scrollSlidingTabStrip.addIconTab(R.drawable.ic_emoji_smile); + scrollSlidingTabStrip.addIconTab(R.drawable.ic_smiles_smile); + + if (showGifs && recentImages != null && !recentImages.isEmpty()) { + scrollSlidingTabStrip.addIconTab(R.drawable.ic_smiles_gif); + gifTabBum = stickersTabOffset; + stickersTabOffset++; + } + if (!recentStickers.isEmpty()) { + recentTabBum = stickersTabOffset; + stickersTabOffset++; scrollSlidingTabStrip.addIconTab(R.drawable.ic_smiles_recent); } + stickerSets.clear(); ArrayList packs = StickersQuery.getStickerSets(); for (int a = 0; a < packs.size(); a++) { @@ -1218,35 +1382,64 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } stickerSets.add(pack); } - Collections.sort(stickerSets, new Comparator() { - @Override - public int compare(TLRPC.TL_messages_stickerSet lhs, TLRPC.TL_messages_stickerSet rhs) { - Integer count1 = stickerSetsUseCount.get(lhs.set.id); - Integer count2 = stickerSetsUseCount.get(rhs.set.id); - if (count1 == null) { - count1 = 0; - } - if (count2 == null) { - count2 = 0; - } - if (count1 > count2) { - return -1; - } else if (count1 < count2) { - return 1; - } - return 0; - } - }); for (int a = 0; a < stickerSets.size(); a++) { scrollSlidingTabStrip.addStickerTab(stickerSets.get(a).documents.get(0)); } + scrollSlidingTabStrip.addIconTab(R.drawable.ic_settings); scrollSlidingTabStrip.updateTabStyles(); + if (lastPosition != 0) { + scrollSlidingTabStrip.onPageScrolled(lastPosition, lastPosition); + } + if (switchToGifTab) { + if (gifTabBum >= 0 && gifsGridView.getVisibility() != VISIBLE) { + showGifTab(); + } + switchToGifTab = false; + } + if (gifTabBum == -2 && gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { + listener.onGifTab(false); + gifsGridView.setVisibility(GONE); + stickersGridView.setVisibility(VISIBLE); + stickersEmptyView.setVisibility(stickersGridAdapter.getCount() != 0 ? GONE : VISIBLE); + } else if (gifTabBum != -2) { + if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { + scrollSlidingTabStrip.onPageScrolled(gifTabBum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); + } else { + scrollSlidingTabStrip.onPageScrolled(stickersGridAdapter.getTabForPosition(stickersGridView.getFirstVisiblePosition()) + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); + } + } + } + + public void addRecentGif(MediaController.SearchImage searchImage) { + if (searchImage == null || searchImage.document == null || recentImages == null) { + return; + } + boolean wasEmpty = recentImages.isEmpty(); + for (int a = 0; a < recentImages.size(); a++) { + MediaController.SearchImage image = recentImages.get(a); + if (image.id.equals(searchImage.id)) { + recentImages.remove(a); + recentImages.add(0, image); + if (gifsAdapter != null) { + gifsAdapter.notifyDataSetChanged(); + } + return; + } + } + recentImages.add(0, searchImage); + if (gifsAdapter != null) { + gifsAdapter.notifyDataSetChanged(); + } + if (wasEmpty) { + updateStickerTabs(); + } } public void loadRecents() { - String str; SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); + lastGifLoadTime = preferences.getLong("lastGifLoadTime", 0); + String str; try { emojiUseHistory.clear(); if (preferences.contains("emojis")) { @@ -1325,16 +1518,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickersUseHistory.put(Long.parseLong(args2[0]), Integer.parseInt(args2[1])); } } - - stickerSetsUseCount.clear(); - str = preferences.getString("sets", ""); - if (str != null && str.length() > 0) { - String[] args = str.split(","); - for (String arg : args) { - String[] args2 = arg.split("="); - stickerSetsUseCount.put(Long.parseLong(args2[0]), Integer.parseInt(args2[1])); - } - } sortStickers(); updateStickerTabs(); } catch (Exception e) { @@ -1408,6 +1591,14 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific super.onAttachedToWindow(); if (stickersGridAdapter != null) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.stickersDidLoaded); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.recentImagesDidLoaded); + } + } + + public void loadGifRecent() { + if (showGifs && gifsAdapter != null && !loadingRecent) { + MessagesStorage.getInstance().loadWebRecent(2); + loadingRecent = true; } } @@ -1419,10 +1610,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific adapters.get(0).notifyDataSetChanged(); if (stickersGridAdapter != null) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.stickersDidLoaded); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.recentImagesDidLoaded); sortStickers(); updateStickerTabs(); reloadStickersAdapter(); + if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE && listener != null) { + listener.onGifTab(true); + } } + loadGifRecent(); } } @@ -1431,17 +1627,97 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific super.onDetachedFromWindow(); if (stickersGridAdapter != null) { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stickersDidLoaded); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.recentImagesDidLoaded); } if (pickerViewPopup != null && pickerViewPopup.isShowing()) { pickerViewPopup.dismiss(); } } + private int calcGifsHash(ArrayList arrayList) { + if (arrayList == null) { + return 0; + } + long acc = 0; + for (int a = 0; a < Math.min(200, arrayList.size()); a++) { + MediaController.SearchImage searchImage = arrayList.get(a); + if (searchImage.document == null) { + continue; + } + int high_id = (int) (searchImage.document.id >> 32); + int lower_id = (int) searchImage.document.id; + acc = ((acc * 20261) + 0x80000000L + high_id) % 0x80000000L; + acc = ((acc * 20261) + 0x80000000L + lower_id) % 0x80000000L; + } + return (int) acc; + } + + public void loadRecentGif() { + if (loadingRecentGifs || Math.abs(System.currentTimeMillis() - lastGifLoadTime) < 60 * 60 * 1000) { + return; + } + loadingRecentGifs = true; + TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs(); + req.hash = calcGifsHash(recentImages); + ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(final TLObject response, TLRPC.TL_error error) { + ArrayList arrayList = null; + if (response instanceof TLRPC.TL_messages_savedGifs) { + arrayList = new ArrayList<>(); + TLRPC.TL_messages_savedGifs res = (TLRPC.TL_messages_savedGifs) response; + int size = res.gifs.size(); + for (int a = 0; a < size; a++) { + MediaController.SearchImage searchImage = new MediaController.SearchImage(); + searchImage.type = 2; + searchImage.document = res.gifs.get(a); + searchImage.date = size - a; + searchImage.id = "" + searchImage.document.id; + arrayList.add(searchImage); + MessagesStorage.getInstance().putWebRecent(arrayList); + } + } + final ArrayList arrayListFinal = arrayList; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (arrayListFinal != null) { + boolean wasEmpty = recentImages.isEmpty(); + recentImages = arrayListFinal; + if (gifsAdapter != null) { + gifsAdapter.notifyDataSetChanged(); + } + lastGifLoadTime = System.currentTimeMillis(); + SharedPreferences.Editor editor = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE).edit(); + editor.putLong("lastGifLoadTime", lastGifLoadTime).commit(); + if (wasEmpty && !recentImages.isEmpty()) { + updateStickerTabs(); + } + } + loadingRecentGifs = false; + } + }); + } + }); + } + + @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, Object... args) { if (id == NotificationCenter.stickersDidLoaded) { updateStickerTabs(); reloadStickersAdapter(); + } else if (id == NotificationCenter.recentImagesDidLoaded) { + if ((Integer) args[0] == 2) { + int previousCount = recentImages != null ? recentImages.size() : 0; + recentImages = (ArrayList) args[1]; + loadingRecent = false; + gifsAdapter.notifyDataSetChanged(); + if (previousCount != recentImages.size()) { + updateStickerTabs(); + } + loadRecentGif(); + } } } @@ -1508,9 +1784,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific int row = position / stickersPerRow; TLRPC.TL_messages_stickerSet pack = rowStartPack.get(row); if (pack == null) { - return 0; + return recentTabBum; } - return stickerSets.indexOf(pack) + (recentStickers.isEmpty() ? 0 : 1); + return stickerSets.indexOf(pack) + stickersTabOffset; } public View getView(int i, View view, ViewGroup viewGroup) { @@ -1689,4 +1965,44 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } } + + private class GifsAdapter extends RecyclerView.Adapter { + + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } + } + + private Context mContext; + + public GifsAdapter(Context context) { + mContext = context; + } + + @Override + public int getItemCount() { + return recentImages.size(); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + ContextLinkCell view = new ContextLinkCell(mContext); + return new Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { + MediaController.SearchImage photoEntry = recentImages.get(i); + if (photoEntry.document != null) { + ((ContextLinkCell) viewHolder.itemView).setGif(photoEntry.document, flowLayoutManager.getRowOfIndex(i) != flowLayoutManager.getRowCount() - 1); + } + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java index 1db8f632..b6cffc56 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java index 282a71c3..930ad191 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java deleted file mode 100644 index 2462db98..00000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java +++ /dev/null @@ -1,409 +0,0 @@ -/* -https://github.com/koral--/android-gif-drawable/ -MIT License -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -package org.telegram.ui.Components; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Looper; -import android.view.View; -import android.widget.MediaController; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.Locale; - -public class GifDrawable extends Drawable implements Animatable, MediaController.MediaPlayerControl { - - private static native void renderFrame(int[] pixels, int gifFileInPtr, int[] metaData); - private static native int openFile(int[] metaData, String filePath); - private static native void free(int gifFileInPtr); - private static native void reset(int gifFileInPtr); - private static native void setSpeedFactor(int gifFileInPtr, float factor); - private static native String getComment(int gifFileInPtr); - private static native int getLoopCount(int gifFileInPtr); - private static native int getDuration(int gifFileInPtr); - private static native int getCurrentPosition(int gifFileInPtr); - private static native int seekToTime(int gifFileInPtr, int pos, int[] pixels); - private static native int seekToFrame(int gifFileInPtr, int frameNr, int[] pixels); - private static native int saveRemainder(int gifFileInPtr); - private static native int restoreRemainder(int gifFileInPtr); - private static native long getAllocationByteCount(int gifFileInPtr); - - private static final Handler UI_HANDLER = new Handler(Looper.getMainLooper()); - - private volatile int mGifInfoPtr; - private volatile boolean mIsRunning = true; - - private final int[] mMetaData = new int[5];//[w, h, imageCount, errorCode, post invalidation time] - private final long mInputSourceLength; - - private float mSx = 1f; - private float mSy = 1f; - private boolean mApplyTransformation; - private final Rect mDstRect = new Rect(); - - public WeakReference parentView = null; - - protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); - protected final int[] mColors; - - private final Runnable mResetTask = new Runnable() { - @Override - public void run() { - reset(mGifInfoPtr); - } - }; - - private final Runnable mStartTask = new Runnable() { - @Override - public void run() { - restoreRemainder(mGifInfoPtr); - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - mMetaData[4] = 0; - } - }; - - private final Runnable mSaveRemainderTask = new Runnable() { - @Override - public void run() { - saveRemainder(mGifInfoPtr); - } - }; - - private final Runnable mInvalidateTask = new Runnable() { - @Override - public void run() { - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - } - }; - - private static void runOnUiThread(Runnable task) { - if (Looper.myLooper() == UI_HANDLER.getLooper()) { - task.run(); - } else { - UI_HANDLER.post(task); - } - } - - public GifDrawable(String filePath) throws Exception { - mInputSourceLength = new File(filePath).length(); - mGifInfoPtr = openFile(mMetaData, filePath); - mColors = new int[mMetaData[0] * mMetaData[1]]; - } - - public GifDrawable(File file) throws Exception { - mInputSourceLength = file.length(); - mGifInfoPtr = openFile(mMetaData, file.getPath()); - mColors = new int[mMetaData[0] * mMetaData[1]]; - } - - public void recycle() { - mIsRunning = false; - int tmpPtr = mGifInfoPtr; - mGifInfoPtr = 0; - free(tmpPtr); - } - - @Override - protected void finalize() throws Throwable { - try { - recycle(); - } finally { - super.finalize(); - } - } - - @Override - public int getIntrinsicHeight() { - return mMetaData[1]; - } - - @Override - public int getIntrinsicWidth() { - return mMetaData[0]; - } - - @Override - public void setAlpha(int alpha) { - mPaint.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter cf) { - mPaint.setColorFilter(cf); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSPARENT; - } - - @Override - public void start() { - if (mIsRunning) { - return; - } - mIsRunning = true; - runOnUiThread(mStartTask); - } - - public void reset() { - runOnUiThread(mResetTask); - } - - @Override - public void stop() { - mIsRunning = false; - runOnUiThread(mSaveRemainderTask); - } - - @Override - public boolean isRunning() { - return mIsRunning; - } - - public String getComment() { - return getComment(mGifInfoPtr); - } - - public int getLoopCount() { - return getLoopCount(mGifInfoPtr); - } - - @Override - public String toString() { - return String.format(Locale.US, "Size: %dx%d, %d frames, error: %d", mMetaData[0], mMetaData[1], mMetaData[2], mMetaData[3]); - } - - public int getNumberOfFrames() { - return mMetaData[2]; - } - - public int getError() { - return mMetaData[3]; - } - - public void setSpeed(float factor) { - if (factor <= 0f) { - throw new IllegalArgumentException("Speed factor is not positive"); - } - setSpeedFactor(mGifInfoPtr, factor); - } - - @Override - public void pause() { - stop(); - } - - @Override - public int getDuration() { - return getDuration(mGifInfoPtr); - } - - @Override - public int getCurrentPosition() { - return getCurrentPosition(mGifInfoPtr); - } - - @Override - public void seekTo(final int position) { - if (position < 0) { - throw new IllegalArgumentException("Position is not positive"); - } - runOnUiThread(new Runnable() { - @Override - public void run() { - seekToTime(mGifInfoPtr, position, mColors); - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - } - }); - } - - public void seekToFrame(final int frameIndex) { - if (frameIndex < 0) { - throw new IllegalArgumentException("frameIndex is not positive"); - } - runOnUiThread(new Runnable() { - @Override - public void run() { - seekToFrame(mGifInfoPtr, frameIndex, mColors); - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - } - }); - } - - @Override - public boolean isPlaying() { - return mIsRunning; - } - - @Override - public int getBufferPercentage() { - return 100; - } - - @Override - public boolean canPause() { - return true; - } - - @Override - public boolean canSeekBackward() { - return false; - } - - @Override - public boolean canSeekForward() { - return getNumberOfFrames() > 1; - } - - @Override - public int getAudioSessionId() { - return 0; - } - - public int getFrameByteCount() { - return mMetaData[0] * mMetaData[1] * 4; - } - - public long getAllocationByteCount() { - return getAllocationByteCount(mGifInfoPtr) + mColors.length * 4L; - } - - public long getInputSourceByteCount() { - return mInputSourceLength; - } - - public void getPixels(int[] pixels) { - if (pixels.length < mColors.length) { - throw new ArrayIndexOutOfBoundsException("Pixels array is too small. Required length: " + mColors.length); - } - System.arraycopy(mColors, 0, pixels, 0, mColors.length); - } - - public int getPixel(int x, int y) { - if (x < 0) { - throw new IllegalArgumentException("x must be >= 0"); - } - if (y < 0) { - throw new IllegalArgumentException("y must be >= 0"); - } - if (x >= mMetaData[0]) { - throw new IllegalArgumentException("x must be < GIF width"); - } - if (y >= mMetaData[1]) { - throw new IllegalArgumentException("y must be < GIF height"); - } - return mColors[mMetaData[1] * y + x]; - } - - public Bitmap getBitmap() { - seekToFrame(mGifInfoPtr, 0, mColors); - return Bitmap.createBitmap(mColors, 0, mMetaData[0], mMetaData[0], mMetaData[1], Bitmap.Config.ARGB_8888); - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - mApplyTransformation = true; - } - - @Override - public void draw(Canvas canvas) { - if (mApplyTransformation) { - mDstRect.set(getBounds()); - mSx = (float) mDstRect.width() / mMetaData[0]; - mSy = (float) mDstRect.height() / mMetaData[1]; - mApplyTransformation = false; - } - if (mPaint.getShader() == null) { - if (mIsRunning) { - renderFrame(mColors, mGifInfoPtr, mMetaData); - } else { - mMetaData[4] = -1; - } - canvas.translate(mDstRect.left, mDstRect.top); - canvas.scale(mSx, mSy); - if (mMetaData[0] > 0 && mMetaData[1] > 0) { - canvas.drawBitmap(mColors, 0, mMetaData[0], 0f, 0f, mMetaData[0], mMetaData[1], true, mPaint); - } - if (mMetaData[4] >= 0 && mMetaData[2] > 1) { - UI_HANDLER.postDelayed(mInvalidateTask, mMetaData[4]); - } - } else { - canvas.drawRect(mDstRect, mPaint); - } - } - - public final Paint getPaint() { - return mPaint; - } - - @Override - public int getAlpha() { - return mPaint.getAlpha(); - } - - @Override - public void setFilterBitmap(boolean filter) { - mPaint.setFilterBitmap(filter); - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - } - - @Override - public void setDither(boolean dither) { - mPaint.setDither(dither); - if (parentView != null && parentView.get() != null) { - parentView.get().invalidate(); - } - } - - @Override - public int getMinimumHeight() { - return mMetaData[1]; - } - - @Override - public int getMinimumWidth() { - return mMetaData[0]; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java index 0d0e70d8..0973d69a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java index fc22433f..b4551abd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java index 60a26421..74e79730 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java index 26e73d7b..70961a7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java index 7c4ba414..e9ffa4b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index 0531e8e9..e5874ffb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -154,15 +154,15 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { final FilterableStateListDrawable selectorDrawable = new FilterableStateListDrawable(); - selectorDrawable.addState(new int[] {-focused, -selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP)); + selectorDrawable.addState(new int[] {-focused, -selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_IN)); selectorDrawable.addState(new int[] {-focused, -selected, -pressed}, nonactiveTab); - selectorDrawable.addState(new int[] {-focused, selected, -pressed}, filteredActiveTab, new PorterDuffColorFilter(tabColor, PorterDuff.Mode.SRC_ATOP)); + selectorDrawable.addState(new int[] {-focused, selected, -pressed}, filteredActiveTab, new PorterDuffColorFilter(tabColor, PorterDuff.Mode.SRC_IN)); selectorDrawable.addState(new int[] {-focused, selected, -pressed}, activeTab); - selectorDrawable.addState(new int[] {pressed}, filteredActiveTab, new PorterDuffColorFilter(tabColor, PorterDuff.Mode.SRC_ATOP)); + selectorDrawable.addState(new int[] {pressed}, filteredActiveTab, new PorterDuffColorFilter(tabColor, PorterDuff.Mode.SRC_IN)); selectorDrawable.addState(new int[] {pressed}, activeTab); - selectorDrawable.addState(new int[]{focused, -selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP)); + selectorDrawable.addState(new int[]{focused, -selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_IN)); selectorDrawable.addState(new int[]{focused, -selected, -pressed}, nonactiveTab); - selectorDrawable.addState(new int[]{focused, selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP)); + selectorDrawable.addState(new int[]{focused, selected, -pressed}, filteredNonactiveTab, new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_IN)); selectorDrawable.addState(new int[]{focused, selected, -pressed}, nonactiveTab); return selectorDrawable; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java index f61de026..eb9b8ed3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java index a6bf8443..9f3e4ae4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java index 137ddc70..d7e3d11d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index 0c14662f..0ecb1b68 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index 9dc34b60..87532d29 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -295,7 +295,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not private void showPopup(int show) { if (show == 1) { if (emojiView == null) { - emojiView = new EmojiView(false, getContext()); + emojiView = new EmojiView(false, false, getContext()); emojiView.setListener(new EmojiView.Listener() { public boolean onBackspace() { if (messageEditText.length() == 0) { @@ -326,6 +326,26 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not public void onStickerSelected(TLRPC.Document sticker) { } + + @Override + public void onStickersSettingsClick() { + + } + + @Override + public void onGifSelected(TLRPC.Document gif) { + + } + + @Override + public void onGifTab(boolean opened) { + + } + + @Override + public void onStickersTab(boolean opened) { + + } }); sizeNotifierLayout.addView(emojiView); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java index 7e6fb2ba..a508a581 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java index 71908c83..7f6be166 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java index d5e7f377..b652dcff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java index ae01fcf1..4064d443 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java @@ -3,19 +3,25 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; +import android.content.SharedPreferences; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.util.Log; import android.view.View; import android.view.animation.DecelerateInterpolator; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLog; public class RadialProgress { @@ -40,6 +46,10 @@ public class RadialProgress { private static DecelerateInterpolator decelerateInterpolator = null; private static Paint progressPaint = null; + private Paint progressText; + private long docSize; + private int docType; + public RadialProgress(View parentView) { if (decelerateInterpolator == null) { decelerateInterpolator = new DecelerateInterpolator(); @@ -48,6 +58,12 @@ public class RadialProgress { progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); } + progressText = new Paint(Paint.ANTI_ALIAS_FLAG); + progressText.setColor(Color.BLACK); + progressText.setTextSize(AndroidUtilities.dp(11)); + progressText.setFakeBoldText(true); + progressText.setTextAlign(Paint.Align.CENTER); + parent = parentView; } @@ -55,38 +71,51 @@ public class RadialProgress { progressRect.set(left, top, right, bottom); } - private void updateAnimation() { + private void updateAnimation(boolean progress) { long newTime = System.currentTimeMillis(); long dt = newTime - lastUpdateTime; lastUpdateTime = newTime; - if (animatedProgressValue != 1) { - radOffset += 360 * dt / 3000.0f; - float progressDiff = currentProgress - animationProgressStart; - if (progressDiff > 0) { - currentProgressTime += dt; - if (currentProgressTime >= 300) { - animatedProgressValue = currentProgress; - animationProgressStart = currentProgress; - currentProgressTime = 0; - } else { - animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f); + if (progress) { + if (animatedProgressValue != 1) { + radOffset += 360 * dt / 3000.0f; + float progressDiff = currentProgress - animationProgressStart; + if (progressDiff > 0) { + currentProgressTime += dt; + if (currentProgressTime >= 300) { + animatedProgressValue = currentProgress; + animationProgressStart = currentProgress; + currentProgressTime = 0; + } else { + animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f); + } } + invalidateParent(); } - invalidateParent(); - } - if (animatedProgressValue >= 1 && previousDrawable != null) { - animatedAlphaValue -= dt / 200.0f; - if (animatedAlphaValue <= 0) { - animatedAlphaValue = 0.0f; - previousDrawable = null; + if (animatedProgressValue >= 1 && previousDrawable != null) { + animatedAlphaValue -= dt / 200.0f; + if (animatedAlphaValue <= 0) { + animatedAlphaValue = 0.0f; + previousDrawable = null; + } + invalidateParent(); + } + } else { + if (previousDrawable != null) { + animatedAlphaValue -= dt / 200.0f; + if (animatedAlphaValue <= 0) { + animatedAlphaValue = 0.0f; + previousDrawable = null; + } + invalidateParent(); } - invalidateParent(); } } public void setProgressColor(int color) { progressColor = color; + SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + progressText.setColor(themePrefs.getInt(color == 0xff87bf78 || color == 0xff81bd72 ? "chatRTextColor" : "chatLTextColor", 0xff000000)); } public void setHideCurrentDrawable(boolean value) { @@ -102,10 +131,14 @@ public class RadialProgress { } currentProgress = value; currentProgressTime = 0; - invalidateParent(); } - + // plus + public void setSizeAndType(long size, int type) { + docSize = size; + docType = type; + } + // private void invalidateParent() { int offset = AndroidUtilities.dp(2); parent.invalidate((int)progressRect.left - offset, (int)progressRect.top - offset, (int)progressRect.right + offset * 2, (int)progressRect.bottom + offset * 2); @@ -124,11 +157,19 @@ public class RadialProgress { } currentWithRound = withRound; currentDrawable = drawable; - invalidateParent(); + if (!animated) { + parent.invalidate(); + } else { + invalidateParent(); + } } - public void swapBackground(Drawable drawable) { - currentDrawable = drawable; + public boolean swapBackground(Drawable drawable) { + if (currentDrawable != drawable) { + currentDrawable = drawable; + return true; + } + return false; } public float getAlpha() { @@ -148,7 +189,7 @@ public class RadialProgress { } else { currentDrawable.setAlpha(255); } - currentDrawable.setBounds((int)progressRect.left, (int)progressRect.top, (int)progressRect.right, (int)progressRect.bottom); + currentDrawable.setBounds((int) progressRect.left, (int) progressRect.top, (int) progressRect.right, (int) progressRect.bottom); currentDrawable.draw(canvas); } @@ -162,7 +203,20 @@ public class RadialProgress { } cicleRect.set(progressRect.left + diff, progressRect.top + diff, progressRect.right - diff, progressRect.bottom - diff); canvas.drawArc(cicleRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint); - updateAnimation(); + if(currentDrawable != null && progressText != null) { + if (currentProgress < 1.0f && docSize > 0) { + if(docType > 0)progressText.setColor(progressColor); + if(docType == 1 || docType == 3 || docType == 8){ + ResourceLoader.mediaBackgroundDrawable.setBounds((int) progressRect.left - AndroidUtilities.dp(20), (int) progressRect.bottom + AndroidUtilities.dp(2), (int) progressRect.right + AndroidUtilities.dp(20) , (int) progressRect.bottom + AndroidUtilities.dp(18)); + ResourceLoader.mediaBackgroundDrawable.draw(canvas); + } + String s = AndroidUtilities.formatFileSize((long) (docSize * currentProgress)) + (docType != 0 ? " | " + String.format(docSize * currentProgress < 104857000 ? "%.1f" : "%.0f", currentProgress * 100) + '%' : ""); //AndroidUtilities.formatFileSize(docSize)*/ //String.format("%.1f", currentProgress * 100) + '%' + canvas.drawText(s, (int) progressRect.left + (currentDrawable.getIntrinsicWidth() / 2) + AndroidUtilities.dp(1), (int) progressRect.bottom + AndroidUtilities.dp(14), progressText); + } + } + updateAnimation(true); + } else { + updateAnimation(false); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java index 39aeab51..f9f7ea69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java index ef88d877..60bc7433 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index 7d29cd0c..21fdedfe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -16,6 +16,7 @@ import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewConfiguration; +import android.view.ViewGroup; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.support.widget.RecyclerView; @@ -40,6 +41,7 @@ public class RecyclerListView extends RecyclerView { private boolean wasPressed; private boolean disallowInterceptTouchEvents; private boolean instantClick; + private Runnable clickRunnable; private static int[] attributes; private static boolean gotAttributes; @@ -69,9 +71,12 @@ public class RecyclerListView extends RecyclerView { view.playSoundEffect(SoundEffectConstants.CLICK); onItemClickListener.onItemClick(view, currentChildPosition); } - AndroidUtilities.runOnUIThread(new Runnable() { + AndroidUtilities.runOnUIThread(clickRunnable = new Runnable() { @Override public void run() { + if (this == clickRunnable) { + clickRunnable = null; + } if (view != null) { view.setPressed(false); if (!instantClick) { @@ -95,10 +100,12 @@ public class RecyclerListView extends RecyclerView { } @Override - public void onLongPress(MotionEvent e) { - if (currentChildView != null && onItemLongClickListener != null) { - if (onItemLongClickListener.onItemClick(currentChildView, currentChildPosition)) { - currentChildView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + public void onLongPress(MotionEvent event) { + if (currentChildView != null) { + if (onItemLongClickListener != null) { + if (onItemLongClickListener.onItemClick(currentChildView, currentChildPosition)) { + currentChildView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } } } } @@ -106,16 +113,31 @@ public class RecyclerListView extends RecyclerView { } @Override - public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { - int action = e.getActionMasked(); + public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent event) { + int action = event.getActionMasked(); boolean isScrollIdle = RecyclerListView.this.getScrollState() == RecyclerListView.SCROLL_STATE_IDLE; if ((action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) && currentChildView == null && isScrollIdle) { - currentChildView = view.findChildViewUnder(e.getX(), e.getY()); + currentChildView = view.findChildViewUnder(event.getX(), event.getY()); + if (currentChildView instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) currentChildView; + float x = event.getX() - currentChildView.getLeft(); + float y = event.getY() - currentChildView.getTop(); + final int count = viewGroup.getChildCount(); + for (int i = count - 1; i >= 0; i--) { + final View child = viewGroup.getChildAt(i); + if (x >= child.getLeft() && x <= child.getRight() && y >= child.getTop() && y <= child.getBottom()) { + if (child.isClickable()) { + currentChildView = null; + break; + } + } + } + } currentChildPosition = -1; if (currentChildView != null) { currentChildPosition = view.getChildPosition(currentChildView); - MotionEvent childEvent = MotionEvent.obtain(0, 0, e.getActionMasked(), e.getX() - currentChildView.getLeft(), e.getY() - currentChildView.getTop(), 0); + MotionEvent childEvent = MotionEvent.obtain(0, 0, event.getActionMasked(), event.getX() - currentChildView.getLeft(), event.getY() - currentChildView.getTop(), 0); if (currentChildView.onTouchEvent(childEvent)) { interceptedByChild = true; } @@ -125,11 +147,11 @@ public class RecyclerListView extends RecyclerView { if (currentChildView != null && !interceptedByChild) { try { - if (e != null) { - mGestureDetector.onTouchEvent(e); + if (event != null) { + mGestureDetector.onTouchEvent(event); } - } catch (Exception ev) { - FileLog.e("tmessages", ev); + } catch (Exception e) { + FileLog.e("tmessages", e); } } @@ -159,24 +181,34 @@ public class RecyclerListView extends RecyclerView { } @Override - public void onTouchEvent(RecyclerView view, MotionEvent e) { + public void onTouchEvent(RecyclerView view, MotionEvent event) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { - if (selectChildRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); - selectChildRunnable = null; - } - if (currentChildView != null) { - currentChildView.setPressed(false); - currentChildView = null; - } - interceptedByChild = false; + cancelClickRunnables(true); } } + public void cancelClickRunnables(boolean uncheck) { + if (selectChildRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); + selectChildRunnable = null; + } + if (currentChildView != null) { + if (uncheck) { + currentChildView.setPressed(false); + } + currentChildView = null; + } + if (clickRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(clickRunnable); + clickRunnable = null; + } + interceptedByChild = false; + } + private AdapterDataObserver observer = new AdapterDataObserver() { @Override public void onChanged() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java index 96fc01e8..31b3775b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -40,28 +40,26 @@ public class ResourceLoader { public static Drawable backgroundBlack; public static Drawable backgroundBlue; public static Drawable mediaBackgroundDrawable; - public static Drawable clockChannelDrawable; + public static Drawable[] clockChannelDrawable = new Drawable[2]; public static Drawable[][] shareDrawable = new Drawable[2][2]; public static Drawable viewsCountDrawable; public static Drawable viewsOutCountDrawable; - public static Drawable viewsMediaCountDrawable; + public static Drawable[] viewsMediaCountDrawable = new Drawable[2]; public static Drawable backgroundWhite; public static Drawable geoInDrawable; public static Drawable geoOutDrawable; - public static Drawable[][] audioStatesDrawable = new Drawable[10][2]; + public static Drawable[][] audioStatesDrawable = new Drawable[10][3]; - public static Drawable placeholderDocInDrawable; - public static Drawable placeholderDocOutDrawable; + public static Drawable[] placeholderDocDrawable = new Drawable[3]; public static Drawable videoIconDrawable; - public static Drawable docMenuInDrawable; - public static Drawable docMenuOutDrawable; + public static Drawable[] docMenuDrawable = new Drawable[3]; public static Drawable[] buttonStatesDrawables = new Drawable[8]; - public static Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][2]; + public static Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][3]; public static void loadRecources(Context context) { //if (backgroundDrawableIn == null) { @@ -80,7 +78,8 @@ public class ResourceLoader { checkMediaDrawable = context.getResources().getDrawable(R.drawable.msg_check_w); halfCheckMediaDrawable = context.getResources().getDrawable(R.drawable.msg_halfcheck_w); clockMediaDrawable = context.getResources().getDrawable(R.drawable.msg_clock_photo); - clockChannelDrawable = context.getResources().getDrawable(R.drawable.msg_clock2); + clockChannelDrawable[0] = context.getResources().getDrawable(R.drawable.msg_clock2); + clockChannelDrawable[1] = context.getResources().getDrawable(R.drawable.msg_clock2_s); errorDrawable = context.getResources().getDrawable(R.drawable.msg_warning); mediaBackgroundDrawable = context.getResources().getDrawable(R.drawable.phototime); broadcastDrawable = context.getResources().getDrawable(R.drawable.broadcast3); @@ -92,31 +91,48 @@ public class ResourceLoader { viewsCountDrawable = context.getResources().getDrawable(R.drawable.post_views); viewsOutCountDrawable = context.getResources().getDrawable(R.drawable.post_viewsg); - viewsMediaCountDrawable = context.getResources().getDrawable(R.drawable.post_views_w); + viewsMediaCountDrawable[0] = context.getResources().getDrawable(R.drawable.post_views_w); + viewsMediaCountDrawable[1] = context.getResources().getDrawable(R.drawable.post_views_s); - audioStatesDrawable[0][0] = context.getResources().getDrawable(R.drawable.play_w2); + audioStatesDrawable[0][2] = audioStatesDrawable[0][0] = context.getResources().getDrawable(R.drawable.play_w2); audioStatesDrawable[0][1] = context.getResources().getDrawable(R.drawable.play_w2_pressed); - audioStatesDrawable[1][0] = context.getResources().getDrawable(R.drawable.pause_w2); + + audioStatesDrawable[1][2] = audioStatesDrawable[1][0] = context.getResources().getDrawable(R.drawable.pause_w2); audioStatesDrawable[1][1] = context.getResources().getDrawable(R.drawable.pause_w2_pressed); + audioStatesDrawable[2][0] = context.getResources().getDrawable(R.drawable.download_g); audioStatesDrawable[2][1] = context.getResources().getDrawable(R.drawable.download_g_pressed); + audioStatesDrawable[2][2] = context.getResources().getDrawable(R.drawable.download_g_s); + audioStatesDrawable[3][0] = context.getResources().getDrawable(R.drawable.pause_g); audioStatesDrawable[3][1] = context.getResources().getDrawable(R.drawable.pause_g_pressed); + audioStatesDrawable[3][2] = context.getResources().getDrawable(R.drawable.pause_g_s); + audioStatesDrawable[4][0] = context.getResources().getDrawable(R.drawable.cancel_g); audioStatesDrawable[4][1] = context.getResources().getDrawable(R.drawable.cancel_g_pressed); - audioStatesDrawable[5][0] = context.getResources().getDrawable(R.drawable.play_w); + audioStatesDrawable[4][2] = context.getResources().getDrawable(R.drawable.cancel_g_s); + + audioStatesDrawable[5][2] = audioStatesDrawable[5][0] = context.getResources().getDrawable(R.drawable.play_w); audioStatesDrawable[5][1] = context.getResources().getDrawable(R.drawable.play_w_pressed); - audioStatesDrawable[6][0] = context.getResources().getDrawable(R.drawable.pause_w); + + audioStatesDrawable[6][2] = audioStatesDrawable[6][0] = context.getResources().getDrawable(R.drawable.pause_w); audioStatesDrawable[6][1] = context.getResources().getDrawable(R.drawable.pause_w_pressed); + audioStatesDrawable[7][0] = context.getResources().getDrawable(R.drawable.download_b); audioStatesDrawable[7][1] = context.getResources().getDrawable(R.drawable.download_b_pressed); + audioStatesDrawable[7][2] = context.getResources().getDrawable(R.drawable.download_b_s); + audioStatesDrawable[8][0] = context.getResources().getDrawable(R.drawable.pause_b); audioStatesDrawable[8][1] = context.getResources().getDrawable(R.drawable.pause_b_pressed); + audioStatesDrawable[8][2] = context.getResources().getDrawable(R.drawable.pause_b_s); + audioStatesDrawable[9][0] = context.getResources().getDrawable(R.drawable.cancel_b); audioStatesDrawable[9][1] = context.getResources().getDrawable(R.drawable.cancel_b_pressed); + audioStatesDrawable[9][2] = context.getResources().getDrawable(R.drawable.cancel_b_s); - placeholderDocInDrawable = context.getResources().getDrawable(R.drawable.doc_blue); - placeholderDocOutDrawable = context.getResources().getDrawable(R.drawable.doc_green); + placeholderDocDrawable[0] = context.getResources().getDrawable(R.drawable.doc_blue); + placeholderDocDrawable[1] = context.getResources().getDrawable(R.drawable.doc_green); + placeholderDocDrawable[2] = context.getResources().getDrawable(R.drawable.doc_blue_s); buttonStatesDrawables[0] = context.getResources().getDrawable(R.drawable.photoload); buttonStatesDrawables[1] = context.getResources().getDrawable(R.drawable.photocancel); buttonStatesDrawables[2] = context.getResources().getDrawable(R.drawable.photogif); @@ -126,14 +142,18 @@ public class ResourceLoader { buttonStatesDrawables[6] = context.getResources().getDrawable(R.drawable.circle); buttonStatesDrawables[7] = context.getResources().getDrawable(R.drawable.photocheck); buttonStatesDrawablesDoc[0][0] = context.getResources().getDrawable(R.drawable.docload_b); - buttonStatesDrawablesDoc[1][0] = context.getResources().getDrawable(R.drawable.doccancel_b); - buttonStatesDrawablesDoc[2][0] = context.getResources().getDrawable(R.drawable.docpause_b); buttonStatesDrawablesDoc[0][1] = context.getResources().getDrawable(R.drawable.docload_g); + buttonStatesDrawablesDoc[0][2] = context.getResources().getDrawable(R.drawable.docload_b_s); + buttonStatesDrawablesDoc[1][0] = context.getResources().getDrawable(R.drawable.doccancel_b); buttonStatesDrawablesDoc[1][1] = context.getResources().getDrawable(R.drawable.doccancel_g); + buttonStatesDrawablesDoc[1][2] = context.getResources().getDrawable(R.drawable.doccancel_b_s); + buttonStatesDrawablesDoc[2][0] = context.getResources().getDrawable(R.drawable.docpause_b); buttonStatesDrawablesDoc[2][1] = context.getResources().getDrawable(R.drawable.docpause_g); + buttonStatesDrawablesDoc[2][2] = context.getResources().getDrawable(R.drawable.docpause_b_s); videoIconDrawable = context.getResources().getDrawable(R.drawable.ic_video); - docMenuInDrawable = context.getResources().getDrawable(R.drawable.doc_actions_b); - docMenuOutDrawable = context.getResources().getDrawable(R.drawable.doc_actions_g); + docMenuDrawable[0] = context.getResources().getDrawable(R.drawable.doc_actions_b); + docMenuDrawable[1] = context.getResources().getDrawable(R.drawable.doc_actions_g); + docMenuDrawable[2] = context.getResources().getDrawable(R.drawable.doc_actions_b_s); shareDrawable[0][0] = context.getResources().getDrawable(R.drawable.shareblue); shareDrawable[0][1] = context.getResources().getDrawable(R.drawable.shareblue_pressed); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java index b1056474..3c199004 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java index 9b315e9e..7e86e75c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java index 676c7acc..bef8b71c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java index 9bb4918e..110cb386 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java index 91f49f8f..54257193 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java index eaf03eaf..e955b854 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java index a793a205..9a840098 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java index cc27b2e6..c7ad2b5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java index 859ee42b..d81c556f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index cd464f6b..8739fb73 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index 6631e295..e50a0c93 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -198,21 +198,6 @@ public class Switch extends CompoundButton { return mSplitTrack; } - /*private void setTheme(){ - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); - int defColor = preferences.getInt("themeColor", AndroidUtilities.defColor); - int sColor = preferences.getInt("prefSectionColor", defColor); - int sDarkColor = AndroidUtilities.getIntAlphaColor("prefSectionColor", sColor, 0.5f); - int darkColor = AndroidUtilities.getIntAlphaColor("themeColor", AndroidUtilities.defColor, 0.5f); - int checkColor = sColor == defColor ? darkColor : sDarkColor; - if (mTrackDrawable != null) { - mTrackDrawable.setColorFilter(new PorterDuffColorFilter(isChecked() ? checkColor : 0xffc7c7c7, PorterDuff.Mode.MULTIPLY)); - } - if (mThumbDrawable != null) { - mThumbDrawable.setColorFilter(new PorterDuffColorFilter(isChecked() ? sColor : 0xffededed, PorterDuff.Mode.MULTIPLY)); - } - }*/ - @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final Rect padding = mTempRect; @@ -433,6 +418,7 @@ public class Switch extends CompoundButton { cancelPositionAnimator(); setThumbPosition(checked ? 1 : 0); } + if(getTag() == null){ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); int defColor = preferences.getInt("themeColor", AndroidUtilities.defColor); int sColor = preferences.getInt("prefSectionColor", defColor); @@ -441,14 +427,28 @@ public class Switch extends CompoundButton { int checkColor = sColor == defColor ? darkColor : sDarkColor; if (mTrackDrawable != null) { //mTrackDrawable.setColorFilter(new PorterDuffColorFilter(checked ? 0xffa0d6fa : 0xffc7c7c7, PorterDuff.Mode.MULTIPLY)); - //mTrackDrawable.setColorFilter(new PorterDuffColorFilter(checked ? AndroidUtilities.getIntAlphaColor("themeColor", AndroidUtilities.defColor, 0.5f) : 0xffc7c7c7, PorterDuff.Mode.MULTIPLY)); mTrackDrawable.setColorFilter(new PorterDuffColorFilter(checked ? checkColor : 0xffc7c7c7, PorterDuff.Mode.MULTIPLY)); } if (mThumbDrawable != null) { //mThumbDrawable.setColorFilter(new PorterDuffColorFilter(checked ? 0xff45abef : 0xffededed, PorterDuff.Mode.MULTIPLY)); - //mThumbDrawable.setColorFilter(new PorterDuffColorFilter(checked ? AndroidUtilities.getIntColor("themeColor") : 0xffededed, PorterDuff.Mode.MULTIPLY)); mThumbDrawable.setColorFilter(new PorterDuffColorFilter(checked ? sColor : 0xffededed, PorterDuff.Mode.MULTIPLY)); } + } + } + + public void setColor(int color){ + boolean checked = isChecked(); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int defColor = preferences.getInt("themeColor", AndroidUtilities.defColor); + int darkColor = AndroidUtilities.getIntAlphaColor("themeColor", AndroidUtilities.defColor, 0.5f); + int sDarkColor = AndroidUtilities.setDarkColor(color, 0x7f); + int checkColor = color == defColor ? darkColor : sDarkColor; + if (mTrackDrawable != null) { + mTrackDrawable.setColorFilter(new PorterDuffColorFilter(checked ? color : 0xffc7c7c7, PorterDuff.Mode.MULTIPLY)); + } + if (mThumbDrawable != null) { + mThumbDrawable.setColorFilter(new PorterDuffColorFilter(checked ? checkColor : 0xffededed, PorterDuff.Mode.MULTIPLY)); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java index 6f363f28..4cf6853b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java index c0a4e650..447543fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; @@ -16,20 +16,46 @@ import android.text.style.MetricAffectingSpan; public class TypefaceSpan extends MetricAffectingSpan { private Typeface mTypeface; + private int textSize; + private int color; public TypefaceSpan(Typeface typeface) { mTypeface = typeface; } + public TypefaceSpan(Typeface typeface, int size) { + mTypeface = typeface; + textSize = size; + } + + public TypefaceSpan(Typeface typeface, int size, int textColor) { + mTypeface = typeface; + textSize = size; + color = textColor; + } + @Override public void updateMeasureState(TextPaint p) { - p.setTypeface(mTypeface); + if (mTypeface != null) { + p.setTypeface(mTypeface); + } + if (textSize != 0) { + p.setTextSize(textSize); + } p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); } @Override public void updateDrawState(TextPaint tp) { - tp.setTypeface(mTypeface); + if (mTypeface != null) { + tp.setTypeface(mTypeface); + } + if (textSize != 0) { + tp.setTextSize(textSize); + } + if (color != 0) { + tp.setColor(color); + } tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java index 567f8001..1663d174 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java index b2ff8881..f6dc2ff1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java index 14c87235..1f54df6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java index 3f9ba71c..539952d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 86c6f781..2719ce94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 2f349a2b..8cfb3479 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index 99b9da90..c7e81ac1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index ce02760b..960ac0dd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 73bb9d5b..4a3fd98a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index af916234..3cbe3a9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java index f8e8cafc..09fea806 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java index 61b620d0..0dcbd1d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java index 3ca2936b..954a197b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 45292363..0e76366c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -14,6 +14,7 @@ import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -175,6 +176,7 @@ public class LanguageSelectActivity extends BaseFragment { localeInfo = LocaleController.getInstance().sortedLanguages.get(i); } } + Log.e("Language","localeInfo " + (localeInfo != null ? localeInfo.shortName : "NULL")); if (localeInfo != null) { LocaleController.getInstance().applyLanguage(localeInfo, true); parentLayout.rebuildAllFragmentViews(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java index a4578363..4d66312b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -296,12 +296,15 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter } else if (currentType == 2) { req.rules.add(new TLRPC.TL_inputPrivacyValueAllowContacts()); } - final ProgressDialog progressDialog = new ProgressDialog(getParentActivity()); + ProgressDialog progressDialog = null; + if (getParentActivity() != null) { + progressDialog = new ProgressDialog(getParentActivity()); progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); progressDialog.setCanceledOnTouchOutside(false); progressDialog.setCancelable(false); progressDialog.show(); - + } + final ProgressDialog progressDialogFinal = progressDialog; ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { @Override public void run(final TLObject response, final TLRPC.TL_error error) { @@ -309,7 +312,9 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter @Override public void run() { try { - progressDialog.dismiss(); + if (progressDialogFinal != null) { + progressDialogFinal.dismiss(); + } } catch (Exception e) { FileLog.e("tmessages", e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java index f9242191..3f145820 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 7669b48a..e95f667b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -17,6 +17,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Point; @@ -27,6 +28,7 @@ import android.os.Parcelable; import android.provider.Browser; import android.provider.ContactsContract; import android.support.annotation.NonNull; +import android.util.Log; import android.view.ActionMode; import android.view.KeyEvent; import android.view.MotionEvent; @@ -120,10 +122,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa private int themesRow = 7; private int themingRow = 8; private int settingsRow = 9; - private int channelRow = 10; - private int communityRow = 11; - private int versionRow = 12; - private int faqRow = 13; + private int plusSettingsRow = 10; + private int channelRow = 11; + private int communityRow = 12; + private int versionRow = 13; + private int faqRow = 14; @Override protected void onCreate(Bundle savedInstanceState) { @@ -153,18 +156,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa requestWindowFeature(Window.FEATURE_NO_TITLE); setTheme(R.style.Theme_TMessages); getWindow().setBackgroundDrawableResource(R.drawable.transparent); - //plus - /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); - int def = themePrefs.getInt("themeColor", AndroidUtilities.defColor); - int hColor = themePrefs.getInt("chatsHeaderColor", def); - - Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); - ActivityManager.TaskDescription td = new ActivityManager.TaskDescription(null, bm, hColor); - - setTaskDescription(td); - bm.recycle(); - }*/ super.onCreate(savedInstanceState); @@ -340,6 +331,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else if (position == themingRow) { presentFragment(new ThemingActivity()); drawerLayoutContainer.closeDrawer(false); + } else if (position == plusSettingsRow) { + presentFragment(new PlusSettingsActivity()); + drawerLayoutContainer.closeDrawer(false); } else if (position == settingsRow) { presentFragment(new SettingsActivity()); drawerLayoutContainer.closeDrawer(false); @@ -425,7 +419,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa NotificationCenter.getInstance().addObserver(this, NotificationCenter.mainUserInfoChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeOtherAppActivities); NotificationCenter.getInstance().addObserver(this, NotificationCenter.didUpdatedConnectionState); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.spamErrorReceived); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.needShowAlert); if (Build.VERSION.SDK_INT < 14) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenStateChanged); } @@ -729,7 +723,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } if (sendingText != null) { - if (sendingText.contains("WhatsApp")) { //who needs this sent from ...? + if (sendingText.contains("WhatsApp")) { //remove unnecessary caption 'sent from WhatsApp' from photos forwarded from WhatsApp sendingText = null; } } @@ -824,7 +818,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } message += data.getQueryParameter("text"); } - } else if (path.length() >= 5) { + } else if (path.length() >= 3) { username = data.getLastPathSegment(); botUser = data.getQueryParameter("start"); botChat = data.getQueryParameter("startgroup"); @@ -1181,15 +1175,19 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else { AlertDialog.Builder builder = new AlertDialog.Builder(LaunchActivity.this); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + if (error.text.startsWith("FLOOD_WAIT")) { + builder.setMessage(LocaleController.getString("FloodWait", R.string.FloodWait)); + } else { builder.setMessage(LocaleController.getString("JoinToGroupErrorNotExist", R.string.JoinToGroupErrorNotExist)); + } builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showAlertDialog(builder); - } } } + } }); } - }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); } else if (state == 1) { TLRPC.TL_messages_importChatInvite req = new TLRPC.TL_messages_importChatInvite(); req.hash = group; @@ -1213,21 +1211,24 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (actionBarLayout != null) { TLRPC.Updates updates = (TLRPC.Updates) response; if (!updates.chats.isEmpty()) { + TLRPC.Chat chat = updates.chats.get(0); + chat.left = false; + chat.kicked = false; MessagesController.getInstance().putUsers(updates.users, false); MessagesController.getInstance().putChats(updates.chats, false); Bundle args = new Bundle(); - int chat_id = updates.chats.get(0).id; - args.putInt("chat_id", chat_id); + args.putInt("chat_id", chat.id); ChatActivity fragment = new ChatActivity(args); NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); actionBarLayout.presentFragment(fragment, false, true, true); - MessagesController.getInstance().generateJoinMessage(chat_id); } } } else { AlertDialog.Builder builder = new AlertDialog.Builder(LaunchActivity.this); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - if (error.text.equals("USERS_TOO_MUCH")) { + if (error.text.startsWith("FLOOD_WAIT")) { + builder.setMessage(LocaleController.getString("FloodWait", R.string.FloodWait)); + } else if (error.text.equals("USERS_TOO_MUCH")) { builder.setMessage(LocaleController.getString("JoinToGroupErrorFull", R.string.JoinToGroupErrorFull)); } else { builder.setMessage(LocaleController.getString("JoinToGroupErrorNotExist", R.string.JoinToGroupErrorNotExist)); @@ -1239,7 +1240,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } }); } - }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); } } else if (sticker != null) { if (!mainFragmentsStack.isEmpty()) { @@ -1417,7 +1418,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa NotificationCenter.getInstance().removeObserver(this, NotificationCenter.mainUserInfoChanged); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeOtherAppActivities); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didUpdatedConnectionState); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.spamErrorReceived); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.needShowAlert); if (Build.VERSION.SDK_INT < 14) { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.screenStateChanged); } @@ -1551,7 +1552,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 3 || requestCode == 4 || requestCode == 5) { - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == 4) { ImageLoader.getInstance().createMediaPaths(); } else if (requestCode == 5) { @@ -1584,6 +1585,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.show(); return; + } else if (requestCode == 2) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.locationPermissionGranted); + } } if (actionBarLayout.fragmentsStack.size() != 0) { BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1); @@ -1661,9 +1666,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else { passcodeView.onResume(); } - AndroidUtilities.checkForCrashes(this); - AndroidUtilities.checkForUpdates(this); - AndroidUtilities.checkForThemes(this); + + if(getPackageName().contains("org.telegram.plus.beta")) { + AndroidUtilities.checkForCrashes(this); + AndroidUtilities.checkForUpdates(this); + } + //AndroidUtilities.checkForThemes(this); ConnectionsManager.getInstance().setAppPaused(false, false); updateCurrentConnectionState(); if (PhotoViewer.getInstance().isVisible()) { @@ -1725,11 +1733,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa onPasscodeResume(); } } - } else if (id == NotificationCenter.spamErrorReceived) { + } else if (id == NotificationCenter.needShowAlert) { final Integer reason = (Integer) args[0]; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + if (reason != 2) { builder.setNegativeButton(LocaleController.getString("MoreInfo", R.string.MoreInfo), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { @@ -1742,10 +1751,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } }); + } if (reason == 0) { builder.setMessage(LocaleController.getString("NobodyLikesSpam1", R.string.NobodyLikesSpam1)); } else if (reason == 1) { builder.setMessage(LocaleController.getString("NobodyLikesSpam2", R.string.NobodyLikesSpam2)); + } else if (reason == 2) { + builder.setMessage((String) args[1]); } if (!mainFragmentsStack.isEmpty()) { mainFragmentsStack.get(mainFragmentsStack.size() - 1).showDialog(builder.create()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index d3cb2278..5ffc506a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -130,6 +130,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter super.onFragmentCreate(); swipeBackEnabled = false; NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeChats); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.locationPermissionGranted); if (messageObject != null) { NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateInterfaces); } @@ -140,6 +141,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public void onFragmentDestroy() { super.onFragmentDestroy(); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.locationPermissionGranted); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats); if (mapView != null) { mapView.onDestroy(); @@ -502,7 +504,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return super.onInterceptTouchEvent(ev); } }; + try { mapView.onCreate(null); + } catch (Exception e) { + FileLog.e("tmessages", e); + } try { MapsInitializer.initialize(context); googleMap = mapView.getMap(); @@ -562,7 +568,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter emptyTextLayout = new LinearLayout(context); emptyTextLayout.setVisibility(View.GONE); emptyTextLayout.setOrientation(LinearLayout.VERTICAL); - frameLayout.addView(emptyTextLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); + frameLayout.addView(emptyTextLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 100, 0, 0)); emptyTextLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -620,7 +626,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } if (googleMap != null) { + try { googleMap.setMyLocationEnabled(true); + } catch (Exception e) { + FileLog.e("tmessages", e); + } googleMap.getUiSettings().setMyLocationButtonEnabled(false); googleMap.getUiSettings().setZoomControlsEnabled(false); googleMap.getUiSettings().setCompassEnabled(false); @@ -891,6 +901,14 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } else if (id == NotificationCenter.closeChats) { removeSelfFromStack(); + } else if (id == NotificationCenter.locationPermissionGranted) { + if (googleMap != null) { + try { + googleMap.setMyLocationEnabled(true); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 833c86e7..cdad6116 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -147,6 +147,14 @@ public class LoginActivity extends BaseFragment { Bundle savedInstanceState = loadCurrentState(); if (savedInstanceState != null) { currentViewNum = savedInstanceState.getInt("currentViewNum", 0); + if (currentViewNum == 1) { + int time = savedInstanceState.getInt("open"); + if (time != 0 && Math.abs(System.currentTimeMillis() / 1000 - time) >= 24 * 60 * 60) { + currentViewNum = 0; + savedInstanceState = null; + clearCurrentState(); + } + } } actionBar.setTitle(views[currentViewNum].getHeaderName()); for (int a = 0; a < views.length; a++) { @@ -175,6 +183,17 @@ public class LoginActivity extends BaseFragment { public void onResume() { super.onResume(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + try { + if (currentViewNum == 1 && views[1] instanceof LoginActivitySmsView) { + int time = ((LoginActivitySmsView) views[1]).openTime; + if (time != 0 && Math.abs(System.currentTimeMillis() / 1000 - time) >= 24 * 60 * 60) { + views[1].onBackPressed(); + setPage(0, false, null, true); + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } } private Bundle loadCurrentState() { @@ -296,7 +315,7 @@ public class LoginActivity extends BaseFragment { } public void setPage(int page, boolean animated, Bundle params, boolean back) { - if (android.os.Build.VERSION.SDK_INT > 13) { + if (android.os.Build.VERSION.SDK_INT > 13 && animated) { final SlideView outView = views[currentViewNum]; final SlideView newView = views[page]; currentViewNum = page; @@ -479,7 +498,6 @@ public class LoginActivity extends BaseFragment { @Override public void afterTextChanged(Editable editable) { if (ignoreOnTextChange) { - ignoreOnTextChange = false; return; } ignoreOnTextChange = true; @@ -518,7 +536,7 @@ public class LoginActivity extends BaseFragment { ignoreSelection = true; countryButton.setText(countriesArray.get(index)); String hint = phoneFormatMap.get(text); - phoneField.setHintText(hint != null ? hint.replace('X', '�') : null); + phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); countryState = 0; } else { countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); @@ -539,6 +557,7 @@ public class LoginActivity extends BaseFragment { phoneField.setSelection(phoneField.length()); } } + ignoreOnTextChange = false; } }); codeField.setOnEditorActionListener(new TextView.OnEditorActionListener() { @@ -729,8 +748,9 @@ public class LoginActivity extends BaseFragment { codeField.setText(code); countryButton.setText(name); String hint = phoneFormatMap.get(code); - phoneField.setHintText(hint != null ? hint.replace('X', '�') : null); + phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); countryState = 0; + ignoreOnTextChange = false; } } @@ -743,6 +763,7 @@ public class LoginActivity extends BaseFragment { ignoreOnTextChange = true; String str = countriesArray.get(i); codeField.setText(countriesMap.get(str)); + ignoreOnTextChange = false; } @Override @@ -883,6 +904,7 @@ public class LoginActivity extends BaseFragment { private Timer timeTimer; private Timer codeTimer; + private int openTime; private final Object timerSync = new Object(); private volatile int time = 60000; private volatile int codeTime = 15000; @@ -918,6 +940,9 @@ public class LoginActivity extends BaseFragment { codeField.setInputType(InputType.TYPE_CLASS_PHONE); codeField.setMaxLines(1); codeField.setPadding(0, 0, 0, 0); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(5); + codeField.setFilters(inputFilters); addView(codeField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, Gravity.CENTER_HORIZONTAL, 0, 20, 0, 0)); codeField.addTextChangedListener(new TextWatcher() { @Override @@ -1029,6 +1054,7 @@ public class LoginActivity extends BaseFragment { requestPhone = params.getString("phoneFormated"); phoneHash = params.getString("phoneHash"); time = params.getInt("calltime"); + openTime = (int) (System.currentTimeMillis() / 1000); if (phone == null) { return; @@ -1247,6 +1273,8 @@ public class LoginActivity extends BaseFragment { } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { needShowAlert(LocaleController.getString("AppName", R.string.AppName), LocaleController.getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(); + setPage(0, true, null, true); needShowAlert(LocaleController.getString("AppName", R.string.AppName), LocaleController.getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { needShowAlert(LocaleController.getString("AppName", R.string.AppName), LocaleController.getString("FloodWait", R.string.FloodWait)); @@ -1299,6 +1327,7 @@ public class LoginActivity extends BaseFragment { if (codeField != null) { ignoreOnTextChange = true; codeField.setText("" + args[0]); + ignoreOnTextChange = false; onNextPressed(); } } @@ -1316,6 +1345,9 @@ public class LoginActivity extends BaseFragment { if (time != 0) { bundle.putInt("time", time); } + if (openTime != 0) { + bundle.putInt("open", openTime); + } } @Override @@ -1328,10 +1360,14 @@ public class LoginActivity extends BaseFragment { if (code != null) { codeField.setText(code); } - Integer t = bundle.getInt("time"); + int t = bundle.getInt("time"); if (t != 0) { time = t; } + int t2 = bundle.getInt("open"); + if (t2 != 0) { + openTime = t2; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index e7d6d938..d896cea5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -1053,7 +1053,7 @@ private final static int quoteforward = 33; } } File f = null; - String fileName = FileLoader.getAttachFileName(message.messageOwner.media.document); + String fileName = message.messageOwner.media != null ? FileLoader.getAttachFileName(message.messageOwner.media.document) : ""; if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { f = new File(message.messageOwner.attachPath); } @@ -1105,7 +1105,7 @@ private final static int quoteforward = 33; } } } else if (!cell.isLoading()) { - FileLoader.getInstance().loadFile(cell.getDocument().messageOwner.media.document, true, false); + FileLoader.getInstance().loadFile(cell.getDocument().messageOwner.media.document, false, false); cell.updateFileExistIcon(); } else { FileLoader.getInstance().cancelLoadFile(cell.getDocument().messageOwner.media.document); @@ -1570,7 +1570,7 @@ private final static int quoteforward = 33; TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; for (int a = 0; a < res.messages.size(); a++) { TLRPC.Message message = res.messages.get(a); - if (message.id > max_id) { + if (max_id != 0 && message.id > max_id) { continue; } messageObjects.add(new MessageObject(message, null, false)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index e6326bcd..5c6f2eac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index 07dd1a6e..db15a693 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index fe00f687..8be4e8e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -72,8 +72,9 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati private TextView dropDown; private ActionBarMenuItem dropDownContainer; private PickerBottomLayout pickerBottomLayout; - private boolean sendPressed = false; - private boolean singlePhoto = false; + private boolean sendPressed; + private boolean singlePhoto; + private boolean allowGifs; private int selectedMode; private ChatActivity chatActivity; @@ -84,10 +85,11 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati public static String imageFilter = "*"; - public PhotoAlbumPickerActivity(boolean singlePhoto, ChatActivity chatActivity) { + public PhotoAlbumPickerActivity(boolean singlePhoto, boolean allowGifs, ChatActivity chatActivity) { super(); this.chatActivity = chatActivity; this.singlePhoto = singlePhoto; + this.allowGifs = allowGifs; } @Override @@ -586,7 +588,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati photoPickerAlbumsCell.requestLayout(); } else if (type == 1) { if (view == null) { - view = new PhotoPickerSearchCell(mContext); + view = new PhotoPickerSearchCell(mContext, allowGifs); ((PhotoPickerSearchCell) view).setDelegate(new PhotoPickerSearchCell.PhotoPickerSearchCellDelegate() { @Override public void didPressedSearchButton(int index) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java index b4cc7b0c..f51a2ebb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 3961e1bd..2b50cfa6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -35,10 +35,18 @@ import org.json.JSONArray; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationCompat.ViewProxy; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.volley.AuthFailureError; import org.telegram.messenger.volley.Request; import org.telegram.messenger.volley.RequestQueue; @@ -46,19 +54,15 @@ import org.telegram.messenger.volley.Response; import org.telegram.messenger.volley.VolleyError; import org.telegram.messenger.volley.toolbox.JsonObjectRequest; import org.telegram.messenger.volley.toolbox.Volley; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.BuildVars; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.RequestDelegate; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Adapters.BaseFragmentAdapter; -import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.Cells.PhotoPickerPhotoCell; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.LayoutHelper; @@ -94,6 +98,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen private boolean giphySearchEndReached = true; private String lastSearchString; private boolean loadingRecent; + private int nextGiphySearchOffset; + private int giphyReqId; + private int lastSearchToken; private MediaController.AlbumEntry selectedAlbum; @@ -221,7 +228,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (type == 0) { searchBingImages(editText.getText().toString(), 0, 53); } else if (type == 1) { - searchGiphyImages(editText.getText().toString(), 0, 53); + nextGiphySearchOffset = 0; + searchGiphyImages(editText.getText().toString(), 0); } lastSearchString = editText.getText().toString(); if (lastSearchString.length() == 0) { @@ -373,7 +381,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (type == 0 && nextSearchBingString != null) { searchBingImages(lastSearchString, searchResult.size(), 54); } else if (type == 1 && !giphySearchEndReached) { - searchGiphyImages(searchItem.getSearchField().getText().toString(), searchResult.size(), 54); + searchGiphyImages(searchItem.getSearchField().getText().toString(), nextGiphySearchOffset); } } } @@ -469,7 +477,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen View view = listView.getChildAt(a); if (view instanceof PhotoPickerPhotoCell) { PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; - int num = (Integer)cell.photoImage.getTag(); + int num = (Integer) cell.photoImage.getTag(); if (selectedAlbum != null) { if (num < 0 || num >= selectedAlbum.photos.size()) { continue; @@ -547,7 +555,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen array = searchResult; } MediaController.SearchImage photoEntry = array.get(index); - if (photoEntry.thumbPath != null) { + if (photoEntry.document != null && photoEntry.document.thumb != null) { + cell.photoImage.setImage(photoEntry.document.thumb.location, null, cell.getContext().getResources().getDrawable(R.drawable.nophotos)); + } else if (photoEntry.thumbPath != null) { cell.photoImage.setImage(photoEntry.thumbPath, null, cell.getContext().getResources().getDrawable(R.drawable.nophotos)); } else if (photoEntry.thumbUrl != null && photoEntry.thumbUrl.length() > 0) { cell.photoImage.setImage(photoEntry.thumbUrl, null, cell.getContext().getResources().getDrawable(R.drawable.nophotos)); @@ -576,7 +586,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen continue; } PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; - int num = (Integer)view.getTag(); + int num = (Integer) view.getTag(); if (selectedAlbum != null) { if (num < 0 || num >= selectedAlbum.photos.size()) { continue; @@ -727,13 +737,79 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } } - private void searchGiphyImages(String query, int offset, final int count) { + private void searchGiphyImages(final String query, int offset) { if (searching) { searching = false; + if (giphyReqId != 0) { + ConnectionsManager.getInstance().cancelRequest(giphyReqId, true); + giphyReqId = 0; + } requestQueue.cancelAll("search"); } - try { searching = true; + TLRPC.TL_messages_searchGifs req = new TLRPC.TL_messages_searchGifs(); + req.q = query; + req.offset = offset; + final int token = ++lastSearchToken; + giphyReqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { + @Override + public void run(final TLObject response, TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (token != lastSearchToken) { + return; + } + if (response != null) { + boolean added = false; + TLRPC.TL_messages_foundGifs res = (TLRPC.TL_messages_foundGifs) response; + nextGiphySearchOffset = res.next_offset; + for (int a = 0; a < res.results.size(); a++) { + TLRPC.FoundGif gif = res.results.get(a); + if (searchResultKeys.containsKey(gif.url)) { + continue; + } + added = true; + MediaController.SearchImage bingImage = new MediaController.SearchImage(); + bingImage.id = gif.url; + if (gif.document != null) { + for (int b = 0; b < gif.document.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = gif.document.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + bingImage.width = attribute.w; + bingImage.height = attribute.h; + break; + } + } + } else { + bingImage.width = gif.w; + bingImage.height = gif.h; + } + bingImage.size = 0; + bingImage.imageUrl = gif.content_url; + bingImage.thumbUrl = gif.thumb_url; + bingImage.localUrl = gif.url + "|" + query; + bingImage.document = gif.document; + if (gif.photo != null && gif.document != null) { + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(gif.photo.sizes, itemWidth, true); + if (size != null) { + gif.document.thumb = size; + } + } + bingImage.type = 1; + searchResult.add(bingImage); + searchResultKeys.put(bingImage.id, bingImage); + } + giphySearchEndReached = !added; + } + searching = false; + updateSearchInterface(); + } + }); + } + }); + ConnectionsManager.getInstance().bindRequestToGuid(giphyReqId, classGuid); + /*try { String url = String.format(Locale.US, "https://api.giphy.com/v1/gifs/search?q=%s&offset=%d&limit=%d&api_key=141Wa2KDAfNfxu", URLEncoder.encode(query, "UTF-8"), offset, count); JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener() { @@ -774,9 +850,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen FileLog.e("tmessages", e); } } - if (!added) { - giphySearchEndReached = true; - } + } catch (Exception e) { FileLog.e("tmessages", e); } @@ -798,12 +872,16 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen requestQueue.add(jsonObjReq); } catch (Exception e) { FileLog.e("tmessages", e); - } + }*/ } private void searchBingImages(String query, int offset, int count) { if (searching) { searching = false; + if (giphyReqId != 0) { + ConnectionsManager.getInstance().cancelRequest(giphyReqId, true); + giphyReqId = 0; + } requestQueue.cancelAll("search"); } try { @@ -950,7 +1028,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen listView.setSelection(position); if (selectedAlbum == null) { - emptyView.setPadding(0, 0, 0, (int)((AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight()) * 0.4f)); + emptyView.setPadding(0, 0, 0, (int) ((AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight()) * 0.4f)); } } @@ -1034,9 +1112,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); MediaController.SearchImage photoEntry; if (searchResult.isEmpty() && lastSearchString == null) { - photoEntry = recentImages.get((Integer)((View)v.getParent()).getTag()); + photoEntry = recentImages.get((Integer) ((View) v.getParent()).getTag()); } else { - photoEntry = searchResult.get((Integer)((View)v.getParent()).getTag()); + photoEntry = searchResult.get((Integer) ((View) v.getParent()).getTag()); } if (selectedWebPhotos.containsKey(photoEntry.id)) { selectedWebPhotos.remove(photoEntry.id); @@ -1088,17 +1166,23 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen imageView.setImage(photoEntry.thumbPath, null, mContext.getResources().getDrawable(R.drawable.nophotos)); } else if (photoEntry.thumbUrl != null && photoEntry.thumbUrl.length() > 0) { imageView.setImage(photoEntry.thumbUrl, null, mContext.getResources().getDrawable(R.drawable.nophotos)); + } else if (photoEntry.document != null && photoEntry.document.thumb != null) { + imageView.setImage(photoEntry.document.thumb.location, null, mContext.getResources().getDrawable(R.drawable.nophotos)); } else { imageView.setImageResource(R.drawable.nophotos); } cell.setChecked(selectedWebPhotos.containsKey(photoEntry.id), false); - showing = PhotoViewer.getInstance().isShowingImage(photoEntry.thumbUrl); + if (photoEntry.document != null) { + showing = PhotoViewer.getInstance().isShowingImage(FileLoader.getPathToAttach(photoEntry.document, true).getAbsolutePath()); + } else { + showing = PhotoViewer.getInstance().isShowingImage(photoEntry.imageUrl); + } } imageView.getImageReceiver().setVisible(!showing, true); cell.checkBox.setVisibility(singlePhoto || showing ? View.GONE : View.VISIBLE); } else if (viewType == 1) { if (view == null) { - LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = li.inflate(R.layout.media_loading_layout, viewGroup, false); } ViewGroup.LayoutParams params = view.getLayoutParams(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 912721c3..15313755 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -44,7 +44,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; -import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; @@ -72,6 +71,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.query.SharedMediaQuery; +import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -80,16 +80,15 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Components.CheckBox; import org.telegram.ui.Components.ClippingImageView; -import org.telegram.ui.Components.GifDrawable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PhotoCropView; import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.PhotoViewerCaptionEnterView; import org.telegram.ui.Components.PickerBottomLayout; +import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto; import java.io.File; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -124,7 +123,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private PickerBottomLayout pickerView; private PickerBottomLayout editorDoneLayout; private RadialProgressView radialProgressViews[] = new RadialProgressView[3]; - private GifDrawable gifDrawable; private ActionBarMenuItem cropItem; private ActionBarMenuItem tuneItem; private ActionBarMenuItem captionItem; @@ -145,7 +143,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ChatActivity parentChatActivity; private MentionsAdapter mentionsAdapter; - private ListView mentionListView; + private RecyclerListView mentionListView; + private LinearLayoutManager mentionLayoutManager; private AnimatorSetProxy mentionListAnimation; private boolean allowMentions; @@ -671,9 +670,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentFileNames[a] != null && currentFileNames[a].equals(location)) { radialProgressViews[a].setProgress(1.0f, true); checkProgress(a, true); - if (a == 0) { - createGifForCurrentImage(); - } break; } } @@ -742,14 +738,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (uid == currentDialogId || uid == mergeDialogId) { if (uid == currentDialogId) { totalImagesCount = (Integer) args[1]; - if ((Boolean) args[2]) { + /*if ((Boolean) args[2]) { SharedMediaQuery.getMediaCount(currentDialogId, SharedMediaQuery.MEDIA_PHOTOVIDEO, classGuid, false); - } + }*/ } else if (uid == mergeDialogId) { totalImagesCountMerge = (Integer) args[1]; - if ((Boolean) args[2]) { + /*if ((Boolean) args[2]) { SharedMediaQuery.getMediaCount(mergeDialogId, SharedMediaQuery.MEDIA_PHOTOVIDEO, classGuid, false); - } + }*/ } if (needSearchImageInArr && isFirstLoading) { isFirstLoading = false; @@ -1397,7 +1393,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onWindowSizeChanged(int size) { - int height = AndroidUtilities.dp(36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0)); + int height = AndroidUtilities.dp(36 * Math.min(3, mentionsAdapter.getItemCount()) + (mentionsAdapter.getItemCount() > 3 ? 18 : 0)); if (size - ActionBar.getCurrentActionBarHeight() * 2 < height) { allowMentions = false; if (mentionListView != null && mentionListView.getVisibility() == View.VISIBLE) { @@ -1415,12 +1411,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }); containerView.addView(captionEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, -400)); - mentionListView = new ListView(parentActivity); + mentionListView = new RecyclerListView(parentActivity); + mentionLayoutManager = new LinearLayoutManager(parentActivity) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + mentionLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + mentionListView.setLayoutManager(mentionLayoutManager); mentionListView.setBackgroundColor(0x7f000000); mentionListView.setVisibility(View.GONE); mentionListView.setClipToPadding(true); - mentionListView.setDividerHeight(0); - mentionListView.setDivider(null); if (Build.VERSION.SDK_INT > 8) { mentionListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER); } @@ -1431,7 +1433,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public void needChangePanelVisibility(boolean show) { if (show) { FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) mentionListView.getLayoutParams(); - int height = 36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0); + int height = 36 * Math.min(3, mentionsAdapter.getItemCount()) + (mentionsAdapter.getItemCount() > 3 ? 18 : 0); layoutParams3.height = AndroidUtilities.dp(height); layoutParams3.topMargin = -AndroidUtilities.dp(height); mentionListView.setLayoutParams(layoutParams3); @@ -1444,6 +1446,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (mentionListView.getVisibility() == View.VISIBLE) { ViewProxy.setAlpha(mentionListView, 1.0f); return; + } else { + mentionLayoutManager.scrollToPositionWithOffset(0, 10000); } if (allowMentions) { mentionListView.setVisibility(View.VISIBLE); @@ -1499,11 +1503,21 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } } + + @Override + public void onContextSearch(boolean searching) { + + } + + @Override + public void onContextClick(TLRPC.BotInlineResult result) { + + } })); - mentionListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + mentionListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onItemClick(View view, int position) { Object object = mentionsAdapter.getItem(position); int start = mentionsAdapter.getResultStartPosition(); int len = mentionsAdapter.getResultLength(); @@ -1518,9 +1532,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }); - mentionListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + mentionListView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { @Override - public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + public boolean onItemClick(View view, int position) { Object object = mentionsAdapter.getItem(position); if (object instanceof String) { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); @@ -2122,7 +2136,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Object object = imagesArrLocals.get(index); if (object instanceof MediaController.SearchImage) { MediaController.SearchImage searchImage = ((MediaController.SearchImage) object); - if (searchImage.localUrl != null && searchImage.localUrl.length() > 0) { + if (searchImage.document != null) { + return FileLoader.getAttachFileName(searchImage.document); + } else if (searchImage.type != 1 && searchImage.localUrl != null && searchImage.localUrl.length() > 0) { File file = new File(searchImage.localUrl); if (file.exists()) { return file.getName(); @@ -2377,6 +2393,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (parentChatActivity != null && parentChatActivity.currentEncryptedChat == null) { mentionsAdapter.setChatInfo(parentChatActivity.info); mentionsAdapter.setNeedUsernames(parentChatActivity.currentChat != null); + mentionsAdapter.setNeedBotContext(false); captionItem.setVisibility(cropItem.getVisibility()); captionEditText.setVisibility(cropItem.getVisibility()); needCaptionLayout = captionItem.getVisibility() == View.VISIBLE; @@ -2535,8 +2552,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat fromCamera = ((MediaController.PhotoEntry) object).bucketId == 0 && ((MediaController.PhotoEntry) object).dateTaken == 0 && imagesArrLocals.size() == 1; caption = ((MediaController.PhotoEntry) object).caption; } else if (object instanceof MediaController.SearchImage) { - currentPathObject = ((MediaController.SearchImage) object).imageUrl; - caption = ((MediaController.SearchImage) object).caption; + MediaController.SearchImage searchImage = (MediaController.SearchImage) object; + if (searchImage.document != null) { + currentPathObject = FileLoader.getPathToAttach(searchImage.document, true).getAbsolutePath(); + } else { + currentPathObject = searchImage.imageUrl; + } + caption = searchImage.caption; } if (fromCamera) { actionBar.setTitle(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); @@ -2635,8 +2657,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat checkProgress(2, false); } } - - createGifForCurrentImage(); } private void setCurrentCaption(final CharSequence caption) { @@ -2666,38 +2686,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - private void createGifForCurrentImage() { - if (gifDrawable != null) { - gifDrawable.recycle(); - gifDrawable = null; - } - if (!imagesArrLocals.isEmpty()) { - if (currentIndex >= 0 && currentIndex < imagesArrLocals.size()) { - Object object = imagesArrLocals.get(currentIndex); - if (!(object instanceof MediaController.SearchImage)) { - return; - } - if (((MediaController.SearchImage) object).type == 1) { - File f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), currentFileNames[0]); - if (!f.exists()) { - f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), currentFileNames[0]); - } - if (f.exists()) { - try { - gifDrawable = new GifDrawable(f); - gifDrawable.parentView = new WeakReference(containerView); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - if (gifDrawable != null) { - gifDrawable.start(); - } - } - } - } - } - } - private void checkProgress(int a, boolean animated) { if (currentFileNames[a] != null) { int index = currentIndex; @@ -2715,18 +2703,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat f = FileLoader.getPathToAttach(location, avatarsUserId != 0); } else if (currentPathObject != null) { f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), currentFileNames[a]); - if (!f.exists()) { + if (!f.exists()) { f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), currentFileNames[a]); } } if (f != null && f.exists()) { - if (currentFileNames[a].endsWith("mp4")) { + if (currentPathObject == null && currentFileNames[a].endsWith("mp4")) { radialProgressViews[a].setBackgroundState(3, animated); } else { radialProgressViews[a].setBackgroundState(-1, animated); } } else { - if (currentFileNames[a].endsWith("mp4")) { + if (currentPathObject == null && currentFileNames[a].endsWith("mp4")) { if (!FileLoader.getInstance().isLoadingFile(currentFileNames[a])) { radialProgressViews[a].setBackgroundState(2, false); } else { @@ -2764,7 +2752,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = placeProvider.getThumbForPhoto(null, null, index); } String path = null; + TLRPC.Document document = null; int imageSize = 0; + String filter = null; if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; if (photoEntry.imagePath != null) { @@ -2773,16 +2763,25 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageReceiver.setOrientation(photoEntry.orientation, false); path = photoEntry.path; } + filter = String.format(Locale.US, "%d_%d", size, size); } else if (object instanceof MediaController.SearchImage) { MediaController.SearchImage photoEntry = (MediaController.SearchImage) object; if (photoEntry.imagePath != null) { path = photoEntry.imagePath; + } else if (photoEntry.document != null) { + document = photoEntry.document; + imageSize = photoEntry.document.size; } else { path = photoEntry.imageUrl; - imageSize = ((MediaController.SearchImage) object).size; + imageSize = photoEntry.size; } + filter = "d"; + } + if (document != null) { + imageReceiver.setImage(document, null, "d", placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, placeHolder == null ? document.thumb.location : null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, false); + } else { + imageReceiver.setImage(path, filter, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, null, imageSize); } - imageReceiver.setImage(path, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, null, imageSize); } else { imageReceiver.setImageBitmap((Bitmap) null); } @@ -3343,10 +3342,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat currentFileLocation = null; currentPathObject = null; currentThumb = null; - if (gifDrawable != null) { - gifDrawable.recycle(); - gifDrawable = null; - } for (int a = 0; a < 3; a++) { if (radialProgressViews[a] != null) { radialProgressViews[a].setBackgroundState(-1, false); @@ -3857,7 +3852,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat tranlateX = -canvas.getWidth() - PAGE_SPACING / 2; } - if (sideImage.getBitmap() != null) { + if (sideImage.hasBitmapImage()) { canvas.save(); canvas.translate(getContainerViewWidth() / 2, getContainerViewHeight() / 2); canvas.translate(canvas.getWidth() + PAGE_SPACING / 2 + tranlateX, 0); @@ -3895,7 +3890,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat alpha = 1.0f - alpha; tranlateX = maxX; } - if (centerImage.getBitmap() != null) { + if (centerImage.hasBitmapImage()) { canvas.save(); canvas.translate(getContainerViewWidth() / 2 + getAdditionX(), getContainerViewHeight() / 2 + getAdditionY()); canvas.translate(tranlateX, currentTranslationY); @@ -3914,17 +3909,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int width = (int) (bitmapWidth * scale); int height = (int) (bitmapHeight * scale); - if (gifDrawable != null) { - canvas.save(); - gifDrawable.setAlpha((int) (alpha * 255)); - gifDrawable.setBounds(-width / 2, -height / 2, width / 2, height / 2); - gifDrawable.draw(canvas); - canvas.restore(); - } else { centerImage.setAlpha(alpha); centerImage.setImageCoords(-width / 2, -height / 2, width, height); centerImage.draw(canvas); - } canvas.restore(); } canvas.save(); @@ -3935,7 +3922,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canvas.restore(); if (sideImage == leftImage) { - if (sideImage.getBitmap() != null) { + if (sideImage.hasBitmapImage()) { canvas.save(); canvas.translate(getContainerViewWidth() / 2, getContainerViewHeight() / 2); canvas.translate(-(canvas.getWidth() * (scale + 1) + PAGE_SPACING) / 2 + currentTranslationX, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 4b175728..979c08ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -329,6 +329,11 @@ public class PopupNotificationActivity extends Activity implements NotificationC public void onWindowSizeChanged(int size) { } + + @Override + public void onStickersTab(boolean opened) { + + } }); messageContainer = new FrameLayoutTouch(this); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 292df8a1..038c0359 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -62,7 +62,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio private int deleteAccountSectionRow; private int deleteAccountRow; private int deleteAccountDetailRow; - private int hideMobileNumberRow; + private int rowCount; @Override @@ -73,7 +73,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio rowCount = 0; privacySectionRow = rowCount++; - hideMobileNumberRow = rowCount++; + blockedRow = rowCount++; lastSeenRow = rowCount++; lastSeenDetailRow = rowCount++; @@ -199,17 +199,6 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } else { presentFragment(new PasscodeActivity(0)); } - } else if (i == hideMobileNumberRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - boolean scr = preferences.getBoolean("hideMobile", false); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("hideMobile", !scr); - editor.commit(); - //AndroidUtilities.hideMobile = !scr; - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!scr); - } - NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged); } } }); @@ -309,8 +298,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio @Override public boolean isEnabled(int i) { - return i == passcodeRow || i == passwordRow || i == blockedRow || i == sessionsRow || i == lastSeenRow && !ContactsController.getInstance().getLoadingLastSeenInfo() || i == deleteAccountRow && !ContactsController.getInstance().getLoadingDeleteInfo() || - i == hideMobileNumberRow; + return i == passcodeRow || i == passwordRow || i == blockedRow || i == sessionsRow || i == lastSeenRow && !ContactsController.getInstance().getLoadingLastSeenInfo() || i == deleteAccountRow && !ContactsController.getInstance().getLoadingDeleteInfo(); } @Override @@ -400,17 +388,6 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } else if (i == deleteAccountSectionRow) { ((HeaderCell) view).setText(LocaleController.getString("DeleteAccountTitle", R.string.DeleteAccountTitle)); } - } else if (type == 3) { - if (view == null) { - view = new TextCheckCell(mContext); - view.setBackgroundColor(0xffffffff); - } - TextCheckCell textCell = (TextCheckCell) view; - - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - if (i == hideMobileNumberRow) { - textCell.setTextAndCheck(LocaleController.getString("HideMobile", R.string.HideMobile), preferences.getBoolean("hideMobile", false), true); - } } return view; } @@ -423,15 +400,13 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio return 1; } else if (i == securitySectionRow || i == deleteAccountSectionRow || i == privacySectionRow) { return 2; - } else if (i == hideMobileNumberRow) { - return 3; } return 0; } @Override public int getViewTypeCount() { - return 4; + return 3; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 399f00f8..dec804f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -320,9 +320,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) && !currentChat.megagroup ? 5 : chat_id)); actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(user_id != 0 || ChatObject.isChannel(chat_id) && !currentChat.megagroup ? 5 : chat_id)); - //Drawable back = context.getResources().getDrawable(R.drawable.ic_ab_back); - //back.setColorFilter(themePrefs.getInt("profileHeaderIconsColor", 0xffffffff), PorterDuff.Mode.MULTIPLY); - //actionBar.setBackButtonDrawable(back); //actionBar.setBackButtonDrawable(new BackDrawable(false)); Drawable back = new BackDrawable(false); ((BackDrawable) back).setColor(themePrefs.getInt("profileHeaderIconsColor", 0xffffffff)); @@ -372,7 +369,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. MessagesController.getInstance().blockUser(user_id); } else { MessagesController.getInstance().unblockUser(user_id); - SendMessagesHelper.getInstance().sendMessage("/start", user_id, null, null, false, false); + SendMessagesHelper.getInstance().sendMessage("/start", user_id, null, null, false, false, null, null); finishFragment(); } } @@ -647,7 +644,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == addMemberRow) { openAddMember(); } else if (position == channelNameRow) { - try { + /*try { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); if (info.about != null && info.about.length() > 0) { @@ -658,7 +655,42 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("BotShare", R.string.BotShare)), 500); } catch (Exception e) { FileLog.e("tmessages", e); - } + }*/ + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setItems(new CharSequence[]{LocaleController.getString("BotShare", R.string.BotShare), LocaleController.getString("Copy", R.string.Copy)}, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (i == 0) { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + if (info.about != null && info.about.length() > 0) { + intent.putExtra(Intent.EXTRA_TEXT, currentChat.title + "\n" + info.about + "\nhttps://telegram.me/" + currentChat.username); + } else { + intent.putExtra(Intent.EXTRA_TEXT, currentChat.title + "\nhttps://telegram.me/" + currentChat.username); + } + getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("BotShare", R.string.BotShare)), 500); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } else if (i == 1) { + try { + if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText("https://telegram.me/" + currentChat.username); + } else { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("label", "https://telegram.me/" + currentChat.username); + clipboard.setPrimaryClip(clip); + } + Toast.makeText(getParentActivity(), LocaleController.formatString("Copied", R.string.Copied, "https://telegram.me/" + currentChat.username), Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + }); + showDialog(builder.create()); } else if (position == leaveChannelRow) { leaveChatPressed(); } else if (position == membersRow || position == blockedUsersRow || position == managementRow) { @@ -796,16 +828,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); } else { - CharSequence[] items = new CharSequence[]{chat_id > 0 ? LocaleController.getString("KickFromGroup", R.string.KickFromGroup) : LocaleController.getString("KickFromBroadcast", R.string.KickFromBroadcast)}; - - builder.setItems(items, new DialogInterface.OnClickListener() { + CharSequence[] items = new CharSequence[]{chat_id > 0 ? LocaleController.getString("KickFromGroup", R.string.KickFromGroup) : LocaleController.getString("KickFromBroadcast", R.string.KickFromBroadcast)}; + builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { if (i == 0) { kickUser(selectedUser); } } - }); + }); } showDialog(builder.create()); return true; @@ -864,7 +895,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (!playProfileAnimation && a == 0) { continue; } - nameTextView[a] = new TextView(context); //nameTextView[a].setTextColor(0xffffffff); nameTextView[a].setTextColor(themePrefs.getInt("profileNameColor", 0xffffffff)); @@ -895,8 +925,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } adminTextView = new TextView(context); - //adminTextView[a].setTextColor(AvatarDrawable.getProfileTextColorForId(user_id != 0 ? 5 : chat_id)); - //adminTextView[a].setTextColor(AndroidUtilities.getIntDarkerColor("themeColor", -0x40)); adminTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); adminTextView.setTextColor(dark); if (oSize < 14)adminTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, oSize); @@ -912,42 +940,26 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (user_id != 0 || chat_id >= 0 && !ChatObject.isLeftFromChat(currentChat)) { writeButton = new ImageView(context); try { - //writeButton.setBackgroundResource(R.drawable.floating_user_states); - Drawable profile = context.getResources().getDrawable(R.drawable.floating_user_states); - if(profile != null)profile.setColorFilter(themePrefs.getInt("profileRowColor", 0xffffffff), PorterDuff.Mode.SRC_IN); - writeButton.setBackgroundDrawable(profile); + writeButton.setBackgroundResource(R.drawable.floating_user_states); + writeButton.getBackground().setColorFilter(themePrefs.getInt("profileRowColor", 0xffffffff), PorterDuff.Mode.SRC_IN); } catch (Throwable e) { FileLog.e("tmessages", e); } writeButton.setScaleType(ImageView.ScaleType.CENTER); int iconColor = themePrefs.getInt("profileIconsColor", 0xff737373); if (user_id != 0) { - //writeButton.setImageResource(R.drawable.floating_message); - if(getParentActivity() != null) { - Drawable message = getParentActivity().getResources().getDrawable(R.drawable.floating_message); - message.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); - writeButton.setImageDrawable(message); - } + writeButton.setImageResource(R.drawable.floating_message); writeButton.setPadding(0, AndroidUtilities.dp(3), 0, 0); } else if (chat_id != 0) { boolean isChannel = ChatObject.isChannel(currentChat); if (isChannel && !currentChat.creator && (!currentChat.megagroup || !currentChat.editor) || !isChannel && !currentChat.admin && !currentChat.creator && currentChat.admins_enabled) { - //writeButton.setImageResource(R.drawable.floating_message); - if(getParentActivity() != null) { - Drawable message = getParentActivity().getResources().getDrawable(R.drawable.floating_message); - message.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); - writeButton.setImageDrawable(message); - } + writeButton.setImageResource(R.drawable.floating_message); writeButton.setPadding(0, AndroidUtilities.dp(3), 0, 0); } else { - //writeButton.setImageResource(R.drawable.floating_camera); - if(getParentActivity() != null) { - Drawable camera = getParentActivity().getResources().getDrawable(R.drawable.floating_camera); - camera.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); - writeButton.setImageDrawable(camera); - } + writeButton.setImageResource(R.drawable.floating_camera); } } + writeButton.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); frameLayout.addView(writeButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP, 0, 0, 16, 0)); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); @@ -1299,7 +1311,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ViewProxy.setTranslationY(onlineTextView[a], (float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float) Math.floor(11 * AndroidUtilities.density) * diff); ViewProxy.setTranslationX(adminTextView, -21 * AndroidUtilities.density * diff); - //ViewProxy.setTranslationY(adminTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(32) + (float) Math.floor(22 * AndroidUtilities.density) * diff); ViewProxy.setTranslationY(adminTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(32 + y2) + (float )Math.floor(22 * AndroidUtilities.density) * diff); ViewProxy.setScaleX(nameTextView[a], 1.0f + 0.12f * diff); @@ -1806,7 +1817,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. sortedUsers.add(i); i++; if(participant instanceof TLRPC.TL_chatParticipantCreator){ - creatorID = participant.user_id; + creatorID = participant.user_id; } } @@ -1895,6 +1906,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + + private void kickUser(int uid) { if (uid != 0) { MessagesController.getInstance().deleteUserFromChat(chat_id, MessagesController.getInstance().getUser(uid), info); @@ -2021,7 +2034,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (currentChat.megagroup && (currentChat.editor || currentChat.creator)) { if (info == null || info.participants_count < MessagesController.getInstance().maxMegagroupCount) { - addMemberRow = rowCount++; + addMemberRow = rowCount++; } } if (participants != null && !participants.isEmpty()) { @@ -2077,6 +2090,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. //updateTheme(); int id = 0; SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + Drawable dots = getParentActivity().getResources().getDrawable(R.drawable.ic_ab_other); + dots.setColorFilter(themePrefs.getInt("profileHeaderIconsColor", 0xffffffff), PorterDuff.Mode.MULTIPLY); if (user_id != 0) { TLRPC.User user = MessagesController.getInstance().getUser(user_id); TLRPC.FileLocation photo = null; @@ -2119,7 +2134,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (!onlineTextView[a].getText().equals(newString2)) { onlineTextView[a].setText(newString2); } - int leftIcon = currentEncryptedChat != null ? R.drawable.ic_lock_header : 0; if (a != 0) { if (user.verified) { @@ -2141,6 +2155,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. adminTextView.setText("id: " + user_id); } + //if(!user.bot){ + // if(user.bot_inline_placeholder != null && user.bot_inline_placeholder.length() > 0)adminTextView.setText(user.bot_inline_placeholder); + //} + avatarImage.getImageReceiver().setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false); } else if (chat_id != 0) { TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id); @@ -2232,21 +2250,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarDrawable.setInfo(chat); avatarImage.setImage(photo, "50_50", avatarDrawable); avatarImage.getImageReceiver().setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false); - - } - /*//Plus: Group and channel profile avatar - TLRPC.FileLocation photo = null; - if (chat.photo != null) { - photo = chat.photo.photo_small; - } - int radius = AndroidUtilities.dp(themePrefs.getInt("profileAvatarRadius", 32)); - AvatarDrawable avatarDrawable = new AvatarDrawable(chat, true); - avatarImage.getImageReceiver().setRoundRadius(radius); - avatarDrawable.setRadius(radius); - avatarImage.setImage(photo, "50_50", avatarDrawable); - }*/ if((BuildConfig.DEBUG)){ final int fId = id; adminTextView.setOnClickListener(new View.OnClickListener() { @@ -2335,13 +2340,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } - /* - private void updateViewColor(View v){ - SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); - int value = themePrefs.getInt("profileRowGradient", 0); - v.setBackgroundColor(0x00000000); - if(value > 0)v.setTag("Profile00");//if gradient make dividercell transparent - }*/ private void createActionBarMenu() { ActionBarMenu menu = actionBar.createMenu(); @@ -2389,44 +2387,39 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. boolean isChannel = ChatObject.isChannel(currentChat); int iconColor = themePrefs.getInt("profileIconsColor", 0xff737373); if (isChannel && !currentChat.creator && (!currentChat.megagroup || !currentChat.editor) || !isChannel && !currentChat.admin && !currentChat.creator && currentChat.admins_enabled) { - //writeButton.setImageResource(R.drawable.floating_message); - if(getParentActivity() != null) { - Drawable message = getParentActivity().getResources().getDrawable(R.drawable.floating_message); - message.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); - writeButton.setImageDrawable(message); - } + writeButton.setImageResource(R.drawable.floating_message); writeButton.setPadding(0, AndroidUtilities.dp(3), 0, 0); } else { - //writeButton.setImageResource(R.drawable.floating_camera); - if(getParentActivity() != null) { - Drawable camera = getParentActivity().getResources().getDrawable(R.drawable.floating_camera); - camera.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); - writeButton.setImageDrawable(camera); - } + writeButton.setImageResource(R.drawable.floating_camera); writeButton.setPadding(0, 0, 0, 0); } + writeButton.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); } if (ChatObject.isChannel(chat)) { ActionBarMenuItem item = null; if (chat.creator) { - item = menu.addItem(10, R.drawable.ic_ab_other); + //item = menu.addItem(10, R.drawable.ic_ab_other); + item = menu.addItem(10, dots); item.addSubItem(edit_channel, LocaleController.getString("ChannelEdit", R.string.ChannelEdit), 0); } else if (chat.megagroup && chat.editor) { - item = menu.addItem(10, R.drawable.ic_ab_other); + //item = menu.addItem(10, R.drawable.ic_ab_other); + item = menu.addItem(10, dots); item.addSubItem(edit_name, LocaleController.getString("EditName", R.string.EditName), 0); } if (!chat.creator && !chat.left && !chat.kicked && chat.megagroup) { if (item == null) { - item = menu.addItem(10, R.drawable.ic_ab_other); + //item = menu.addItem(10, R.drawable.ic_ab_other); + item = menu.addItem(10, dots); } item.addSubItem(leave_group, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu), 0); } } else { - ActionBarMenuItem item = menu.addItem(10, R.drawable.ic_ab_other); + //ActionBarMenuItem item = menu.addItem(10, R.drawable.ic_ab_other); + ActionBarMenuItem item = menu.addItem(10, dots); if (chat.creator && chat_id > 0) { item.addSubItem(set_admins, LocaleController.getString("SetAdmins", R.string.SetAdmins), 0); } - if (chat.creator || chat.admin) { + if (!chat.admins_enabled || chat.creator || chat.admin) { item.addSubItem(edit_name, LocaleController.getString("EditName", R.string.EditName), 0); } item.addSubItem(leave_group, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit), 0); @@ -2672,10 +2665,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. textCell.setTextAndValue(LocaleController.getString("MessageLifetime", R.string.MessageLifetime), value); textCell.setValueColor(vColor); } else if (i == settingsNotificationsRow) { - //textCell.setTextAndIcon(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.profile_list); - Drawable pf = mContext.getResources().getDrawable(R.drawable.profile_list); - pf.setColorFilter(dColor, PorterDuff.Mode.SRC_IN); - textCell.setTextAndIcon(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), pf); + textCell.setTextAndIcon(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.profile_list); + textCell.setIconColor(dColor); } else if (i == startSecretChatRow) { textCell.setText(LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); //textCell.setTextColor(0xff37a919); @@ -2725,15 +2716,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (participants != null) { TLRPC.ChannelParticipant part = participants.get(i - emptyRowChat2 - 1); int icon = 0; - if (creatorID == part.user_id) { + if (part instanceof TLRPC.TL_channelParticipantCreator || part instanceof TLRPC.TL_channelParticipantEditor) { icon = R.drawable.menu_admin; } //((UserCell) holder.itemView).setData(MessagesController.getInstance().getUser(part.user_id), null, null, i == emptyRowChat2 + 1 ? R.drawable.menu_newgroup : 0); - ((UserCell) holder.itemView).setData(MessagesController.getInstance().getUser(part.user_id), null, null, i == emptyRowChat2 + 1 ? R.drawable.menu_newgroup : icon); + ((UserCell) holder.itemView).setData(MessagesController.getInstance().getUser(part.user_id), null, null, icon != 0 ? icon : i == emptyRowChat2 + 1 ? R.drawable.menu_newgroup : 0); } else { TLRPC.ChatParticipant part = info.participants.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)); int icon = 0; - if (creatorID == part.user_id) { + if (creatorID == part.user_id || (currentChat != null && currentChat.admins_enabled && part instanceof TLRPC.TL_chatParticipantAdmin)) { icon = R.drawable.menu_admin; } else if (part.user_id == UserConfig.getClientUserId()) { icon = R.drawable.menu_contacts; @@ -2747,23 +2738,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. aboutLinkCell.setTextColor(tColor); aboutLinkCell.setLinkColor(themePrefs.getInt("profileSummaryColor", def)); if (i == botInfoRow) { - //aboutLinkCell.setTextAndIcon(botInfo.share_text, R.drawable.bot_info); - Drawable bot = mContext.getResources().getDrawable(R.drawable.bot_info); - if(bot!= null){ - bot.setColorFilter(dColor, PorterDuff.Mode.SRC_IN); - aboutLinkCell.setTextAndIcon(botInfo.share_text, bot); - } + aboutLinkCell.setTextAndIcon(botInfo.share_text, R.drawable.bot_info); + aboutLinkCell.setIconColor(dColor); } else if (i == channelInfoRow) { String text = info.about; while (text.contains("\n\n\n")) { text = text.replace("\n\n\n", "\n\n"); } - //aboutLinkCell.setTextAndIcon(text, R.drawable.bot_info); - Drawable bot = mContext.getResources().getDrawable(R.drawable.bot_info); - if(bot!= null){ - bot.setColorFilter(dColor, PorterDuff.Mode.SRC_IN); - aboutLinkCell.setTextAndIcon(text, bot); - } + aboutLinkCell.setTextAndIcon(text, R.drawable.bot_info); + aboutLinkCell.setIconColor(dColor); } break; default: diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 32315ae6..786af766 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java index 9ca19d12..edcc97be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 229033fd..f934369e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 970e4517..4d325e5e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -35,6 +35,7 @@ import android.text.Spannable; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.util.Base64; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -48,6 +49,8 @@ import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; @@ -59,7 +62,6 @@ import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.BuildConfig; import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -81,7 +83,9 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.ShadowSectionCell; @@ -107,6 +111,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private BackupImageView avatarImage; private TextView nameTextView; private TextView onlineTextView; + //private TextView statusTextView; private ImageView writeButton; private AnimatorSetProxy writeButtonAnimation; private AvatarUpdater avatarUpdater = new AvatarUpdater(); @@ -137,6 +142,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private int messagesSectionRow2; private int textSizeRow; private int stickersRow; + private int cacheRow; private int sendByEnterRow; private int supportSectionRow; private int supportSectionRow2; @@ -149,18 +155,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private int contactsSectionRow; private int contactsReimportRow; private int contactsSortRow; + private int autoplayGifsRow; private int rowCount; - private int disableMessageClickRow; - private int showAndroidEmojiRow; - private int useDeviceFontRow; - private int keepOriginalFilenameRow; - private int keepOriginalFilenameDetailRow; - private int emojiPopupSize; - private int disableAudioStopRow; - private int dialogsSectionRow; - private int dialogsSectionRow2; - private int dialogsPicClickRow; - private int dialogsGroupPicClickRow; private final static int edit_name = 1; private final static int logout = 2; @@ -235,11 +231,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }; NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateInterfaces); - + SharedPreferences plusPreferences = ApplicationLoader.applicationContext.getSharedPreferences("plusconfig", Activity.MODE_PRIVATE); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + boolean hideMobile = plusPreferences.getBoolean("hideMobile", false); rowCount = 0; overscrollRow = rowCount++; emptyRow = rowCount++; - if(!AndroidUtilities.getBoolMain("hideMobile")){ + if(!plusPreferences.getBoolean("hideMobile", false)){ numberSectionRow = rowCount++; numberRow = rowCount++; } @@ -251,41 +249,30 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter backgroundRow = rowCount++; languageRow = rowCount++; enableAnimationsRow = rowCount++; - if (android.os.Build.VERSION.SDK_INT >= 19) { // Only enable this option for Kitkat and newer android versions - showAndroidEmojiRow = rowCount++; - } else { - showAndroidEmojiRow = -1; - } - useDeviceFontRow = rowCount++; + mediaDownloadSection = rowCount++; mediaDownloadSection2 = rowCount++; mobileDownloadRow = rowCount++; wifiDownloadRow = rowCount++; roamingDownloadRow = rowCount++; + if (Build.VERSION.SDK_INT >= 11) { + autoplayGifsRow = rowCount++; + } saveToGalleryRow = rowCount++; - keepOriginalFilenameRow = rowCount++; - keepOriginalFilenameDetailRow = rowCount++; - messagesSectionRow = rowCount++; + messagesSectionRow = rowCount++; messagesSectionRow2 = rowCount++; textSizeRow = rowCount++; stickersRow = rowCount++; - emojiPopupSize = rowCount++; - sendByEnterRow = rowCount++; - disableAudioStopRow = rowCount++; - disableMessageClickRow = rowCount++; + cacheRow = rowCount++; - dialogsSectionRow = rowCount++; - dialogsSectionRow2 = rowCount++; - dialogsPicClickRow = rowCount++; - dialogsGroupPicClickRow = rowCount++; + sendByEnterRow = rowCount++; supportSectionRow = rowCount++; supportSectionRow2 = rowCount++; askQuestionRow = rowCount++; telegramFaqRow = rowCount++; - //if (BuildVars.DEBUG_VERSION) { - if (BuildConfig.DEBUG) { + if (BuildVars.DEBUG_VERSION) { sendLogsRow = rowCount++; clearLogsRow = rowCount++; --switchBackendButtonRow; @@ -421,19 +408,19 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SharedPreferences.Editor editor = preferences.edit(); editor.putInt("fons_size", numberPicker.getValue()); MessagesController.getInstance().fontSize = numberPicker.getValue(); - editor.commit(); + editor.apply(); // SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); SharedPreferences.Editor edit = themePrefs.edit(); edit.putInt("chatTextSize", numberPicker.getValue()); - edit.commit(); + edit.apply();; if (listView != null) { listView.invalidateViews(); } } }); showDialog(builder.create()); - } else if (i == emojiPopupSize) { + } /*else if (i == emojiPopupSize) { if (getParentActivity() == null) { return; } @@ -443,7 +430,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter numberPicker.setMinValue(60); numberPicker.setMaxValue(100); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emoji", Activity.MODE_PRIVATE); - numberPicker.setValue(preferences.getInt("emojiPopupSize", 60)); + numberPicker.setValue(preferences.getInt("emojiPopupSize", AndroidUtilities.isTablet() ? 65 : 60)); builder.setView(numberPicker); builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() { @Override @@ -451,52 +438,22 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emoji", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putInt("emojiPopupSize", numberPicker.getValue()); - editor.commit(); + editor.apply();; if (listView != null) { listView.invalidateViews(); } } }); showDialog(builder.create()); - } else if (i == enableAnimationsRow) { + }*/ else if (i == enableAnimationsRow) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); boolean animations = preferences.getBoolean("view_animations", true); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("view_animations", !animations); - editor.commit(); + editor.apply();; if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!animations); } - } else if (i == showAndroidEmojiRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - boolean enabled = preferences.getBoolean("showAndroidEmoji", false); - editor.putBoolean("showAndroidEmoji", !enabled); - editor.commit(); - ApplicationLoader.SHOW_ANDROID_EMOJI = !enabled; - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!enabled); - } - } else if (i == useDeviceFontRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - boolean enabled = preferences.getBoolean("useDeviceFont", false); - editor.putBoolean("useDeviceFont", !enabled); - editor.commit(); - ApplicationLoader.USE_DEVICE_FONT = !enabled; - AndroidUtilities.needRestart = true; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (getParentActivity() != null) { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("AppWillRestart", R.string.AppWillRestart), Toast.LENGTH_SHORT); - toast.show(); - } - } - }); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!enabled); - } } else if (i == notificationRow) { presentFragment(new NotificationsSettingsActivity()); } else if (i == backgroundRow) { @@ -530,27 +487,14 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter boolean send = preferences.getBoolean("send_by_enter", false); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("send_by_enter", !send); - editor.commit(); + editor.apply();; if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!send); } - } else if (i == disableAudioStopRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - boolean send = preferences.getBoolean("disableAudioStop", false); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("disableAudioStop", !send); - editor.commit(); + } else if (i == autoplayGifsRow) { + MediaController.getInstance().toggleAutoplayGifs(); if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!send); - } - } else if (i == disableMessageClickRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - boolean send = preferences.getBoolean("disableMessageClick", false); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("disableMessageClick", !send); - editor.commit(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!send); + ((TextCheckCell) view).setChecked(MediaController.getInstance().canAutoplayGifs()); } } else if (i == saveToGalleryRow) { MediaController.getInstance().toggleSaveToGallery(); @@ -601,7 +545,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putInt("sortContactsBy", which); - editor.commit(); + editor.apply();; if (listView != null) { listView.invalidateViews(); } @@ -613,70 +557,112 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (getParentActivity() == null) { return; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + final boolean maskValues[] = new boolean[6]; + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); int mask = 0; if (i == mobileDownloadRow) { - builder.setTitle(LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData)); - mask = MediaController.getInstance().mobileDataDownloadMask; - } else if (i == wifiDownloadRow) { - builder.setTitle(LocaleController.getString("WhenConnectedOnWiFi", R.string.WhenConnectedOnWiFi)); - mask = MediaController.getInstance().wifiDownloadMask; - } else if (i == roamingDownloadRow) { - builder.setTitle(LocaleController.getString("WhenRoaming", R.string.WhenRoaming)); - mask = MediaController.getInstance().roamingDownloadMask; + mask = MediaController.getInstance().mobileDataDownloadMask; + } else if (i == wifiDownloadRow) { + mask = MediaController.getInstance().wifiDownloadMask; + } else if (i == roamingDownloadRow) { + mask = MediaController.getInstance().roamingDownloadMask; + } + + builder.setApplyTopPaddings(false); + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + for (int a = 0; a < 6; a++) { + String name = null; + if (a == 0) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_PHOTO) != 0; + name = LocaleController.getString("AttachPhoto", R.string.AttachPhoto); + } else if (a == 1) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_AUDIO) != 0; + name = LocaleController.getString("AttachAudio", R.string.AttachAudio); + } else if (a == 2) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_VIDEO) != 0; + name = LocaleController.getString("AttachVideo", R.string.AttachVideo); + } else if (a == 3) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_DOCUMENT) != 0; + name = LocaleController.getString("AttachDocument", R.string.AttachDocument); + } else if (a == 4) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_MUSIC) != 0; + name = LocaleController.getString("AttachMusic", R.string.AttachMusic); + } else if (a == 5) { + if (Build.VERSION.SDK_INT >= 11) { + maskValues[a] = (mask & MediaController.AUTODOWNLOAD_MASK_GIF) != 0; + name = LocaleController.getString("AttachGif", R.string.AttachGif); + } else { + continue; + } } - builder.setMultiChoiceItems( - new CharSequence[]{LocaleController.getString("AttachPhoto", R.string.AttachPhoto), LocaleController.getString("AttachAudio", R.string.AttachAudio), LocaleController.getString("AttachVideo", R.string.AttachVideo), LocaleController.getString("AttachDocument", R.string.AttachDocument)}, - new boolean[]{(mask & MediaController.AUTODOWNLOAD_MASK_PHOTO) != 0, (mask & MediaController.AUTODOWNLOAD_MASK_AUDIO) != 0, (mask & MediaController.AUTODOWNLOAD_MASK_VIDEO) != 0, (mask & MediaController.AUTODOWNLOAD_MASK_DOCUMENT) != 0}, - new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - int mask = 0; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - if (i == mobileDownloadRow) { - mask = MediaController.getInstance().mobileDataDownloadMask; - } else if (i == wifiDownloadRow) { - mask = MediaController.getInstance().wifiDownloadMask; - } else if (i == roamingDownloadRow) { - mask = MediaController.getInstance().roamingDownloadMask; - } - - int maskDiff = 0; - if (which == 0) { - maskDiff = MediaController.AUTODOWNLOAD_MASK_PHOTO; - } else if (which == 1) { - maskDiff = MediaController.AUTODOWNLOAD_MASK_AUDIO; - } else if (which == 2) { - maskDiff = MediaController.AUTODOWNLOAD_MASK_VIDEO; - } else if (which == 3) { - maskDiff = MediaController.AUTODOWNLOAD_MASK_DOCUMENT; - } - - if (isChecked) { - mask |= maskDiff; - } else { - mask &= ~maskDiff; - } - - if (i == mobileDownloadRow) { - editor.putInt("mobileDataDownloadMask", mask); - MediaController.getInstance().mobileDataDownloadMask = mask; - } else if (i == wifiDownloadRow) { - editor.putInt("wifiDownloadMask", mask); - MediaController.getInstance().wifiDownloadMask = mask; - } else if (i == roamingDownloadRow) { - editor.putInt("roamingDownloadMask", mask); - MediaController.getInstance().roamingDownloadMask = mask; - } - editor.commit(); - if (listView != null) { - listView.invalidateViews(); - } + CheckBoxCell checkBoxCell = new CheckBoxCell(getParentActivity()); + checkBoxCell.setTag(a); + checkBoxCell.setBackgroundResource(R.drawable.list_selector); + linearLayout.addView(checkBoxCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + checkBoxCell.setText(name, "", maskValues[a], true); + checkBoxCell.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CheckBoxCell cell = (CheckBoxCell) v; + int num = (Integer) cell.getTag(); + maskValues[num] = !maskValues[num]; + cell.setChecked(maskValues[num], true); + } + }); + } + BottomSheet.BottomSheetCell cell = new BottomSheet.BottomSheetCell(getParentActivity(), 2); + cell.setBackgroundResource(R.drawable.list_selector); + cell.setTextAndIcon(LocaleController.getString("Save", R.string.Save).toUpperCase(), 0); + cell.setTextColor(0xffcd5a5a); + cell.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + if (visibleDialog != null) { + visibleDialog.dismiss(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + int newMask = 0; + for (int a = 0; a < 6; a++) { + if (maskValues[a]) { + if (a == 0) { + newMask |= MediaController.AUTODOWNLOAD_MASK_PHOTO; + } else if (a == 1) { + newMask |= MediaController.AUTODOWNLOAD_MASK_AUDIO; + } else if (a == 2) { + newMask |= MediaController.AUTODOWNLOAD_MASK_VIDEO; + } else if (a == 3) { + newMask |= MediaController.AUTODOWNLOAD_MASK_DOCUMENT; + } else if (a == 4) { + newMask |= MediaController.AUTODOWNLOAD_MASK_MUSIC; + } else if (a == 5) { + newMask |= MediaController.AUTODOWNLOAD_MASK_GIF; } - }); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + } + } + SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit(); + if (i == mobileDownloadRow) { + editor.putInt("mobileDataDownloadMask", newMask); + MediaController.getInstance().mobileDataDownloadMask = newMask; + } else if (i == wifiDownloadRow) { + editor.putInt("wifiDownloadMask", newMask); + MediaController.getInstance().wifiDownloadMask = newMask; + } else if (i == roamingDownloadRow) { + editor.putInt("roamingDownloadMask", newMask); + MediaController.getInstance().roamingDownloadMask = newMask; + } + editor.apply();; + if (listView != null) { + listView.invalidateViews(); + } + } + }); + linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + builder.setCustomView(linearLayout); showDialog(builder.create()); } else if (i == usernameRow) { presentFragment(new ChangeUsernameActivity()); @@ -684,64 +670,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter presentFragment(new ChangePhoneHelpActivity()); } else if (i == stickersRow) { presentFragment(new StickersActivity()); - } else if (i == keepOriginalFilenameRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - boolean keep = preferences.getBoolean("keepOriginalFilename", false); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("keepOriginalFilename", !keep); - editor.commit(); - ApplicationLoader.KEEP_ORIGINAL_FILENAME = !keep; - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(!keep); - } - } else if (i == dialogsPicClickRow) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("ClickOnContactPic", R.string.ClickOnContactPic)); - builder.setItems(new CharSequence[]{ - LocaleController.getString("RowGradientDisabled", R.string.RowGradientDisabled), - LocaleController.getString("ShowPics", R.string.ShowPics), - LocaleController.getString("ShowProfile", R.string.ShowProfile) - }, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("dialogsClickOnPic", which); - editor.commit(); - if (listView != null) { - listView.invalidateViews(); - } - } - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - } else if (i == dialogsGroupPicClickRow) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("ClickOnGroupPic", R.string.ClickOnGroupPic)); - builder.setItems(new CharSequence[]{ - LocaleController.getString("RowGradientDisabled", R.string.RowGradientDisabled), - LocaleController.getString("ShowPics", R.string.ShowPics), - LocaleController.getString("ShowProfile", R.string.ShowProfile) - }, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("dialogsClickOnGroupPic", which); - editor.commit(); - if (listView != null) { - listView.invalidateViews(); - } - } - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); + } else if (i == cacheRow) { + presentFragment(new CacheControlActivity()); } } }); @@ -757,14 +687,16 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter shadowView = new View(context); shadowView.setBackgroundResource(R.drawable.header_shadow); frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3)); - + SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); avatarImage = new BackupImageView(context); //avatarImage.setRoundRadius(AndroidUtilities.dp(21)); int radius = AndroidUtilities.getIntDef("prefAvatarRadius", 32); avatarImage.setRoundRadius(radius); ViewProxy.setPivotX(avatarImage, 0); ViewProxy.setPivotY(avatarImage, 0); - frameLayout.addView(avatarImage, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); + int aSize = themePrefs.getInt("prefAvatarSize", 42); + //frameLayout.addView(avatarImage, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); + frameLayout.addView(avatarImage, LayoutHelper.createFrame(aSize, aSize, Gravity.LEFT, 64, 0, 0, 0)); avatarImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -803,6 +735,17 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter onlineTextView.setGravity(Gravity.LEFT); frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + //statusTextView = new TextView(context); + //statusTextView.setText("TEST"); + //statusTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + //statusTextView.setTextColor(preferences.getInt("prefHeaderStatusColor", AndroidUtilities.getIntDarkerColor("themeColor", -0x40))); + //statusTextView.setLines(1); + //statusTextView.setMaxLines(1); + //statusTextView.setSingleLine(true); + //statusTextView.setEllipsize(TextUtils.TruncateAt.END); + //statusTextView.setGravity(Gravity.LEFT); + //frameLayout.addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + writeButton = new ImageView(context); writeButton.setBackgroundResource(R.drawable.floating_user_states); if(bgColor != 0xffffffff) { @@ -1025,7 +968,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SerializedData data = new SerializedData(); res.user.serializeToStream(data); editor.putString("support_user", Base64.encodeToString(data.toByteArray(), Base64.DEFAULT)); - editor.commit(); + editor.apply();; data.cleanup(); try { progressDialog.dismiss(); @@ -1115,7 +1058,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter Drawable other = getParentActivity().getResources().getDrawable(R.drawable.ic_ab_other); other.setColorFilter(themePrefs.getInt("prefHeaderIconsColor", 0xffffffff), PorterDuff.Mode.MULTIPLY); - } @Override @@ -1138,7 +1080,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (avatarImage != null) { float diff = extraHeight / (float) AndroidUtilities.dp(88); - ViewProxy.setScaleY(extraHeightView, diff); ViewProxy.setTranslationY(shadowView, newTop + extraHeight); @@ -1193,18 +1134,28 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter }); writeButtonAnimation.start(); } - - ViewProxy.setScaleX(avatarImage, (42 + 18 * diff) / 42.0f); - ViewProxy.setScaleY(avatarImage, (42 + 18 * diff) / 42.0f); + SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); + int aSize = themePrefs.getInt("prefAvatarSize", 42); + //ViewProxy.setScaleX(avatarImage, (42 + 18 * diff) / 42.0f); + //ViewProxy.setScaleY(avatarImage, (42 + 18 * diff) / 42.0f); + ViewProxy.setScaleX(avatarImage, (aSize + 18 * diff) / (aSize *1.0f)); + ViewProxy.setScaleY(avatarImage, (aSize + 18 * diff) / (aSize * 1.0f)); float avatarY = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() / 2.0f * (1.0f + diff) - 21 * AndroidUtilities.density + 27 * AndroidUtilities.density * diff; ViewProxy.setTranslationX(avatarImage, -AndroidUtilities.dp(47) * diff); ViewProxy.setTranslationY(avatarImage, (float) Math.ceil(avatarY)); ViewProxy.setTranslationX(nameTextView, -21 * AndroidUtilities.density * diff); ViewProxy.setTranslationY(nameTextView, (float) Math.floor(avatarY) - (float) Math.ceil(AndroidUtilities.density) + (float) Math.floor(7 * AndroidUtilities.density * diff)); ViewProxy.setTranslationX(onlineTextView, -21 * AndroidUtilities.density * diff); - ViewProxy.setTranslationY(onlineTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float )Math.floor(11 * AndroidUtilities.density) * diff); + ViewProxy.setTranslationY(onlineTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float) Math.floor(11 * AndroidUtilities.density) * diff); + //ViewProxy.setTranslationX(statusTextView, -21 * AndroidUtilities.density * diff); + //ViewProxy.setTranslationY(statusTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(32) + (float) Math.floor(22 * AndroidUtilities.density) * diff); ViewProxy.setScaleX(nameTextView, 1.0f + 0.12f * diff); ViewProxy.setScaleY(nameTextView, 1.0f + 0.12f * diff); + //if (diff > 0.85) { + // statusTextView.setVisibility(View.VISIBLE); + //} else { + // statusTextView.setVisibility(View.GONE); + //} } } @@ -1305,11 +1256,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public boolean isEnabled(int i) { - return i == textSizeRow || i == enableAnimationsRow || i == notificationRow || i == backgroundRow || i == numberRow || i == showAndroidEmojiRow || i == useDeviceFontRow || i == emojiPopupSize || - i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == privacyRow || i == wifiDownloadRow || i == disableAudioStopRow || i == disableMessageClickRow || + return i == textSizeRow || i == enableAnimationsRow || i == notificationRow || i == backgroundRow || i == numberRow || + i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == autoplayGifsRow || i == privacyRow || i == wifiDownloadRow || i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow || i == usernameRow || - i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow || i == keepOriginalFilenameRow || - i == stickersRow || i == dialogsPicClickRow || i == dialogsGroupPicClickRow; + i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow || + i == stickersRow || i == cacheRow; } @Override @@ -1359,10 +1310,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SharedPreferences themePrefs = ApplicationLoader.applicationContext.getSharedPreferences(AndroidUtilities.THEME_PREFS, AndroidUtilities.THEME_PREFS_MODE); int size = themePrefs.getInt("chatTextSize", AndroidUtilities.isTablet() ? 18 : 16); textCell.setTextAndValue(LocaleController.getString("TextSize", R.string.TextSize), String.format("%d", size), true); - } else if (i == emojiPopupSize) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emoji", Activity.MODE_PRIVATE); - int size = preferences.getInt("emojiPopupSize", AndroidUtilities.isTablet() ? 65 : 60); - textCell.setTextAndValue(LocaleController.getString("EmojiPopupSize", R.string.EmojiPopupSize), String.format("%d", size), true); } else if (i == languageRow) { textCell.setTextAndValue(LocaleController.getString("Language", R.string.Language), LocaleController.getCurrentLanguageName(), true); } else if (i == contactsSortRow) { @@ -1397,30 +1344,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter textCell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); } else if (i == stickersRow) { textCell.setText(LocaleController.getString("Stickers", R.string.Stickers), true); - } else if (i == dialogsPicClickRow) { - String value; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - int sort = preferences.getInt("dialogsClickOnPic", 0); - if (sort == 0) { - value = LocaleController.getString("RowGradientDisabled", R.string.RowGradientDisabled); - } else if (sort == 1) { - value = LocaleController.getString("ShowPics", R.string.ShowPics); - } else { - value = LocaleController.getString("ShowProfile", R.string.ShowProfile); - } - textCell.setTextAndValue(LocaleController.getString("ClickOnContactPic", R.string.ClickOnContactPic), value, false); - } else if (i == dialogsGroupPicClickRow) { - String value; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - int sort = preferences.getInt("dialogsClickOnGroupPic", 0); - if (sort == 0) { - value = LocaleController.getString("RowGradientDisabled", R.string.RowGradientDisabled); - } else if (sort == 1) { - value = LocaleController.getString("ShowPics", R.string.ShowPics); - } else { - value = LocaleController.getString("ShowProfile", R.string.ShowProfile); - } - textCell.setTextAndValue(LocaleController.getString("ClickOnGroupPic", R.string.ClickOnGroupPic), value, true); + } else if (i == cacheRow) { + textCell.setText(LocaleController.getString("CacheSettings", R.string.CacheSettings), true); } } else if (type == 3) { if (view == null) { @@ -1433,18 +1358,10 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter textCell.setTextAndCheck(LocaleController.getString("EnableAnimations", R.string.EnableAnimations), preferences.getBoolean("view_animations", true), true); } else if (i == sendByEnterRow) { textCell.setTextAndCheck(LocaleController.getString("SendByEnter", R.string.SendByEnter), preferences.getBoolean("send_by_enter", false), true); - } else if (i == disableAudioStopRow) { - textCell.setTextAndCheck(LocaleController.getString("DisableAudioStop", R.string.DisableAudioStop), preferences.getBoolean("disableAudioStop", false), true); - } else if (i == disableMessageClickRow) { - textCell.setTextAndCheck(LocaleController.getString("DisableMessageClick", R.string.DisableMessageClick), preferences.getBoolean("disableMessageClick", false), false); } else if (i == saveToGalleryRow) { textCell.setTextAndCheck(LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), MediaController.getInstance().canSaveToGallery(), true); - } else if (i == keepOriginalFilenameRow) { - textCell.setTextAndCheck(LocaleController.getString("KeepOriginalFilename", R.string.KeepOriginalFilename), ApplicationLoader.KEEP_ORIGINAL_FILENAME, false); - } else if (i == showAndroidEmojiRow) { - textCell.setTextAndCheck(LocaleController.getString("ShowAndroidEmoji", R.string.ShowAndroidEmoji), ApplicationLoader.SHOW_ANDROID_EMOJI, true); - } else if (i == useDeviceFontRow) { - textCell.setTextAndCheck(LocaleController.getString("UseDeviceFont", R.string.UseDeviceFont), ApplicationLoader.USE_DEVICE_FONT, false); + } else if (i == autoplayGifsRow) { + textCell.setTextAndCheck(LocaleController.getString("AutoplayGifs", R.string.AutoplayGifs), MediaController.getInstance().canAutoplayGifs(), true); } } else if (type == 4) { if (view == null) { @@ -1460,8 +1377,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter ((HeaderCell) view).setText(LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload)); } else if (i == numberSectionRow) { ((HeaderCell) view).setText(LocaleController.getString("Info", R.string.Info)); - }else if (i == dialogsSectionRow2) { - ((HeaderCell) view).setText(LocaleController.getString("DialogsSettings", R.string.DialogsSettings)); } } else if (type == 5) { if (view == null) { @@ -1515,6 +1430,20 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } text += LocaleController.getString("AttachDocument", R.string.AttachDocument); } + if ((mask & MediaController.AUTODOWNLOAD_MASK_MUSIC) != 0) { + if (text.length() != 0) { + text += ", "; + } + text += LocaleController.getString("AttachMusic", R.string.AttachMusic); + } + if (Build.VERSION.SDK_INT >= 11) { + if ((mask & MediaController.AUTODOWNLOAD_MASK_GIF) != 0) { + if (text.length() != 0) { + text += ", "; + } + text += LocaleController.getString("AttachGif", R.string.AttachGif); + } + } if (text.length() == 0) { text = LocaleController.getString("NoMediaAutoDownload", R.string.NoMediaAutoDownload); } @@ -1538,14 +1467,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } textCell.setTextAndValue(value, LocaleController.getString("Username", R.string.Username), false); } - } else if (type == 7) { - if (view == null) { - view = new TextInfoPrivacyCell(mContext); - } - if (i == keepOriginalFilenameDetailRow) { - ((TextInfoPrivacyCell) view).setText(LocaleController.getString("KeepOriginalFilenameHelp", R.string.KeepOriginalFilenameHelp)); - view.setBackgroundResource(R.drawable.greydivider); - } } return view; } @@ -1555,19 +1476,17 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (i == emptyRow || i == overscrollRow) { return 0; } - if (i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow || i == dialogsSectionRow) { + if (i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) { return 1; - } else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow || i == disableAudioStopRow || i == disableMessageClickRow || i == showAndroidEmojiRow || i == useDeviceFontRow || i == keepOriginalFilenameRow ) { + } else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow || i == autoplayGifsRow) { return 3; - } else if (i == notificationRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == privacyRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow || i == textSizeRow || i == emojiPopupSize || i == languageRow || i == contactsSortRow || i == stickersRow || i == dialogsPicClickRow || i == dialogsGroupPicClickRow) { + } else if (i == notificationRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == privacyRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow || i == textSizeRow || i == languageRow || i == contactsSortRow || i == stickersRow || i == cacheRow) { return 2; } else if (i == versionRow) { return 5; } else if (i == wifiDownloadRow || i == mobileDownloadRow || i == roamingDownloadRow || i == numberRow || i == usernameRow) { return 6; - } else if (i == keepOriginalFilenameDetailRow) { - return 7; - } else if (i == settingsSectionRow2 || i == messagesSectionRow2 || i == supportSectionRow2 || i == numberSectionRow || i == mediaDownloadSection2 || i == dialogsSectionRow2) { + } else if (i == settingsSectionRow2 || i == messagesSectionRow2 || i == supportSectionRow2 || i == numberSectionRow || i == mediaDownloadSection2) { return 4; } else { return 2; @@ -1576,7 +1495,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public int getViewTypeCount() { - return 8; + return 7; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingActivity.java index 9039c319..38a2ca71 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatActivity.java index 4525355d..f2288058 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -665,11 +665,8 @@ public class ThemingChatActivity extends BaseFragment { if (getParentActivity() == null) { return; } - LayoutInflater li = (LayoutInflater)getParentActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - li.inflate(R.layout.colordialog, null, false); - ColorSelectorDialog colorDialog = new ColorSelectorDialog(getParentActivity(), new OnColorChangedListener() { @Override public void colorChanged(int color) { @@ -677,7 +674,6 @@ public class ThemingChatActivity extends BaseFragment { } },themePrefs.getInt(key, 0xffffffff), CENTER, 0, true); - colorDialog.show(); } else if (i == rTextColorRow) { if (getParentActivity() == null) { @@ -805,7 +801,7 @@ public class ThemingChatActivity extends BaseFragment { public void colorChanged(int color) { commitInt( key, color); } - },themePrefs.getInt( key, 0xffffffff), CENTER, 0, false); + },themePrefs.getInt( key, 0xffffffff), CENTER, 0, true); colorDialog.show(); } else if (i == nameColorRow) { if (getParentActivity() == null) { @@ -1130,7 +1126,7 @@ public class ThemingChatActivity extends BaseFragment { builder.setTitle(LocaleController.getString("AvatarSize", R.string.AvatarSize)); final NumberPicker numberPicker = new NumberPicker(getParentActivity()); final int currentValue = themePrefs.getInt( key, 42); - numberPicker.setMinValue(1); + numberPicker.setMinValue(0); numberPicker.setMaxValue(56); numberPicker.setValue(currentValue); builder.setView(numberPicker); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatsActivity.java index e10bb2e9..97c56c78 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingChatsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -268,7 +268,7 @@ public class ThemingChatsActivity extends BaseFragment { public void colorChanged(int color) { commitInt(key, color); } - },themePrefs.getInt( key, 0xffffffff), CENTER, 0, false); + },themePrefs.getInt( key, 0xffffffff), CENTER, 0, true); colorDialog.show(); } else if (i == rowColorRow) { if (getParentActivity() == null) { @@ -673,7 +673,7 @@ public class ThemingChatsActivity extends BaseFragment { builder.setTitle(LocaleController.getString("AvatarSize", R.string.AvatarSize)); final NumberPicker numberPicker = new NumberPicker(getParentActivity()); final int currentValue = themePrefs.getInt( key, 52); - numberPicker.setMinValue(1); + numberPicker.setMinValue(0); numberPicker.setMaxValue(72); numberPicker.setValue(currentValue); builder.setView(numberPicker); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingContactsActivity.java index 5542cdd6..0ad14751 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingContactsActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -213,7 +213,7 @@ public class ThemingContactsActivity extends BaseFragment { public void colorChanged(int color) { commitInt( "contactsHeaderIconsColor", color); } - },themePrefs.getInt( "contactsHeaderIconsColor", 0xffffffff), CENTER, 0, false); + },themePrefs.getInt( "contactsHeaderIconsColor", 0xffffffff), CENTER, 0, true); colorDialog.show(); } else if (i == iconsColorRow) { if (getParentActivity() == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingDrawerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingDrawerActivity.java index 95d84090..3ccf1d8a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingDrawerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingDrawerActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -453,7 +453,7 @@ public class ThemingDrawerActivity extends BaseFragment { builder.setTitle(LocaleController.getString("AvatarSize", R.string.AvatarSize)); final NumberPicker numberPicker = new NumberPicker(getParentActivity()); final int currentValue = themePrefs.getInt("drawerAvatarSize", 64); - numberPicker.setMinValue(1); + numberPicker.setMinValue(0); numberPicker.setMaxValue(75); numberPicker.setValue(currentValue); builder.setView(numberPicker); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemingProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemingProfileActivity.java index ae4e5855..623fae12 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemingProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemingProfileActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -264,7 +264,7 @@ public class ThemingProfileActivity extends BaseFragment { public void colorChanged(int color) { commitInt( key, color); } - },themePrefs.getInt( key, 0xffffffff), CENTER, 0, false); + },themePrefs.getInt( key, 0xffffffff), CENTER, 0, true); colorDialog.show(); } else if (i == iconsColorRow) { if (getParentActivity() == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java index 214a2c65..58296692 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index fe59e10b..b41852d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -18,6 +18,7 @@ import android.media.MediaCodecInfo; import android.media.MediaPlayer; import android.os.Build; import android.os.Bundle; +import android.util.Log; import android.view.Gravity; import android.view.Surface; import android.view.TextureView; @@ -100,7 +101,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur private SeekBar bar; private int barValue; - private long tBitrate = 0; + //private long tBitrate = 0; public interface VideoEditorActivityDelegate { void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration); @@ -255,6 +256,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur if (compressVideo.getVisibility() == View.GONE || compressVideo.getVisibility() == View.VISIBLE && !compressVideo.isChecked()) { delegate.didFinishEditVideo(videoPath, startTime, endTime, originalWidth, originalHeight, rotationValue, originalWidth, originalHeight, originalBitrate, estimatedSize, esimatedDuration); } else { + Log.e("VideoEditor","resultWidth "+ resultWidth + " resultHeight " + resultHeight + " bitrate " + bitrate + " estimatedSize " + estimatedSize + " esimatedDuration " + esimatedDuration); delegate.didFinishEditVideo(videoPath, startTime, endTime, resultWidth, resultHeight, rotationValue, originalWidth, originalHeight, bitrate, estimatedSize, esimatedDuration); } } @@ -525,8 +527,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur int width = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth; int height = rotationValue == 90 || rotationValue == 270 ? originalWidth : originalHeight; String videoDimension = String.format("%dx%d", width, height); - long duration = (long)Math.ceil(videoDuration); - int minutes = (int)(duration / 1000 / 60); + long duration = (long) Math.ceil(videoDuration); + int minutes = (int) (duration / 1000 / 60); int seconds = (int) Math.ceil(duration / 1000) - minutes * 60; String videoTimeSize = String.format("%d:%02d, %s", minutes, seconds, AndroidUtilities.formatFileSize(originalSize)); originalSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize)); @@ -536,19 +538,21 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur if (editedSizeTextView == null) { return; } - esimatedDuration = (long)Math.ceil((videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration); + esimatedDuration = (long) Math.ceil((videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration); int width; int height; + calculate(); + if (compressVideo.getVisibility() == View.GONE || compressVideo.getVisibility() == View.VISIBLE && !compressVideo.isChecked()) { width = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth; height = rotationValue == 90 || rotationValue == 270 ? originalWidth : originalHeight; - estimatedSize = (int)(originalSize * ((float)esimatedDuration / videoDuration)); + estimatedSize = (int) (originalSize * ((float) esimatedDuration / videoDuration)); } else { width = rotationValue == 90 || rotationValue == 270 ? resultHeight : resultWidth; height = rotationValue == 90 || rotationValue == 270 ? resultWidth : resultHeight; - estimatedSize = calculateEstimatedSize((float)esimatedDuration / videoDuration); + estimatedSize = calculateEstimatedSize((float) esimatedDuration / videoDuration); } if (videoTimelineView.getLeftProgress() == 0) { @@ -563,7 +567,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } String videoDimension = String.format("%dx%d", width, height); - int minutes = (int)(esimatedDuration / 1000 / 60); + int minutes = (int) (esimatedDuration / 1000 / 60); int seconds = (int) Math.ceil(esimatedDuration / 1000) - minutes * 60; String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, AndroidUtilities.formatFileSize(estimatedSize)); editedSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize)); @@ -769,7 +773,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } for (Box box : boxes) { - TrackBox trackBox = (TrackBox)box; + TrackBox trackBox = (TrackBox) box; long sampleSizes = 0; long trackBitrate = 0; try { @@ -779,15 +783,16 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur for (long size : sampleSizeBox.getSampleSizes()) { sampleSizes += size; } - videoDuration = (float)mediaHeaderBox.getDuration() / (float)mediaHeaderBox.getTimescale(); - trackBitrate = (int)(sampleSizes * 8 / videoDuration); + videoDuration = (float) mediaHeaderBox.getDuration() / (float) mediaHeaderBox.getTimescale(); + trackBitrate = (int) (sampleSizes * 8 / videoDuration); + //tBitrate = trackBitrate; } catch (Exception e) { FileLog.e("tmessages", e); } TrackHeaderBox headerBox = trackBox.getTrackHeaderBox(); if (headerBox.getWidth() != 0 && headerBox.getHeight() != 0) { trackHeaderBox = headerBox; - tBitrate = trackBitrate; + //tBitrate = trackBitrate; originalBitrate = bitrate = (int)(trackBitrate / 100000 * 100000); if (bitrate > 900000) { bitrate = 900000; @@ -809,8 +814,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } else if (matrix.equals(Matrix.ROTATE_270)) { rotationValue = 270; } - resultWidth = originalWidth = (int)trackHeaderBox.getWidth(); - resultHeight = originalHeight = (int)trackHeaderBox.getHeight(); + resultWidth = originalWidth = (int) trackHeaderBox.getWidth(); + resultHeight = originalHeight = (int) trackHeaderBox.getHeight(); if (resultWidth > 640 || resultHeight > 640) { float scale = resultWidth > resultHeight ? 640.0f / resultWidth : 640.0f / resultHeight; @@ -818,7 +823,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur resultHeight *= scale; if (bitrate != 0) { bitrate *= Math.max(0.5f, scale); - videoFramesSize = (long)(bitrate / 8 * videoDuration); + videoFramesSize = (long) (bitrate / 8 * videoDuration); } } @@ -839,32 +844,33 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } private void calculate(){ - videoDuration /= 1000; + //videoDuration /= 1000; resultWidth = originalWidth; resultHeight = originalHeight; - - bitrate = (int)(tBitrate / 100000 * 100000); + //bitrate = (int)(tBitrate / 100000 * 100000); + bitrate = originalBitrate; bitrate /= barValue; int x = 2; + //int minSize = 640; if(barValue > 4) { - if (resultWidth > 640 * x || resultHeight > 640 * x) { - if(barValue > 14)x = 1; + if (originalWidth > 640 * x || originalHeight > 640 * x || barValue > 8) { + if(barValue > 14 || Math.max(originalWidth, originalHeight) <= 640*2)x = 1; float scale = resultWidth > resultHeight ? 640.0f * x / resultWidth : 640.0f * x / resultHeight; - //Log.e("scale", scale + ""); if (barValue > 6) resultWidth *= scale; if (barValue > 6) resultHeight *= scale; bitrate *= Math.max(0.5f, scale); } } - if (bitrate != 0)videoFramesSize = (long) (bitrate / 8 * videoDuration); - //Log.e("bitrate",bitrate+""); - videoDuration *= 1000; + if (bitrate != 0){ + videoFramesSize = (long) (bitrate / 8 * (videoDuration/1000)); + } + //videoDuration *= 1000; } private int calculateEstimatedSize(float timeDelta) { - int size = (int)((audioFramesSize + videoFramesSize) * timeDelta); + int size = (int) ((audioFramesSize + videoFramesSize) * timeDelta); size += size / (32 * 1024) * 16; return size; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java index 83b13fe4..5e5e0b97 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java @@ -3,7 +3,7 @@ * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2015. + * Copyright Nikolai Kudashov, 2013-2016. */ package org.telegram.ui; @@ -372,7 +372,11 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); } if (toFile.exists()) { - backgroundImage.setImageURI(Uri.fromFile(toFile)); + try{ + backgroundImage.setImageURI(Uri.fromFile(toFile)); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } else { selectedBackground = 1000001; processSelectedBackground(); diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/Thumbs.db b/TMessagesProj/src/main/res/drawable-xxhdpi/Thumbs.db index de93aeb47cac335baf05620d9a055d950e562783..fa5f56fd98a4f4a27156c79a2bb6cb11c607cb73 100644 GIT binary patch literal 1097728 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%0Dm;y(!GF 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

saiO)P^Wh1NRopGr}7;yS5 zyuKzeeG_==X&4H=g6V$NfkED0c+8d^7^*GyGMG@0#!2ecY(CHFPmavVb`1Mq{P&x+ zWw=&x56A-@#&VDK7y3dO`$9D=SKo2_ydMxjuPM*Pkj`Q#b-h@sSD_q$pN@`gP*LqM zQib|P+EsBS^e}$A+lWRsGs^vKUTj@~shjEX{^+Wg^=UKrd!GK({I#Keuj~HdTzsnD zN*e3ggl}l;&pu&YFbEwe(L9nLOco(CXng zuCt3{QVBTK3=hRaa>Ma!HyXhv9-e(wf^^~UBZ^g5=s;5jA5?^ zxj$8R4;{b4< z9Cneb(Z{G_lTow@q<-SeGT)JCa9=wdww*p4`e@Xo7yf2f>1`{u0(EFo+JIe#(9V~j z{nuf;=9zABp8 z4;No^Yx$c^WokOjv`^yFS+dkS9d>!C9u?w=e_**uCQj_iU7y6m^nT3pMGaP^8O}Mg z<{_`*IpMdWkJ4pH6-5}XxYCto1!sG{c;c`8$sZZ!5>%RTx>UH`s*P))d!#g4pL<6W z*Fu6edj7+NP@>cWGv8R7ydJzv<;4211SN8{eD0p;vDNWetIs%MI4z&&$NF+*)&uOY zgXkwI@?|Q(TWU`4E;8(-KNP@uJ@jbrgCR;n=b3 z`{~=K{x?M%4-|`d7GiHw3CkRrY`So|NaJ)EeJ8hxbsQE`Sqcv@{mL6vw!87s=+&)y zt!+x8(bZ!wwL;Ii3nSaiIzQ5}UyDMl}?C;wX z|K|MH3jVP5^8BZ{V2}R${1*sn0gnMefM7rf0MWN03{1lTPXG~sNI(=I8W01B1;hcK z0^$J)fJ8tNAQ_MXNCl(;(g7KOOh6VO8;}Ed2FL~E0rCL_0Py7i^c+wGcma3`CN&#hnazF*367UA_7ElGK2Gjs*0d;_SKm(u=fY>*1!v?hgS^;fI4lo6n2Fw6v0ds(Pzye?qumo5JtN>O4 z?*ShGYk+mYM*w0wKY{6Iz!$(KU<>dSunpJ&>;k?4_5k~U1HgB{A>asb3^)P&0GtBO z0Ox=Uz)t`Ku9^R;{|7GfpZcqQIgK1mw-ZWdfi{Lz1^bKJk8j~%z-r2s0(BnfS!&TU z-p0U?Bhj&E%s>sd-=mKtV1lD)V`!tSO9`+`8;-(l^9aH%fPfrVMa^=QK zDl8`SY;~5P88tp-<-sw#FN`Z_rEGk-$rKU&I)~-!P!Qa#PSRxGG(ucYjoiZ-d{2Fk~GANRDfX&9PSbvV;)P9 z|CnCHGG_8e-U;%Q3C+KKKwyu*vpN#k*ksyOhp~5;C8b~eSpOvLWR~ofe~K%E(^w}& z4E1EJXzUin9Zi#U(3rCAHt^uYcI3$TPd_bx^Z>v0#wy7!g$VXGu0pHks^>h>UV{Yg z$)Yz-ap4rSh2j)quX&SZ4^|^|oQ0U{7?xn_4#tQO(isliU)8Q9ETN$dy1L@DD!zMO zP6>wj@$y2q%s2@wUz^V~Uge#o+aq7ZoJG2Ovk=`>%ZtfUx!0`x&?ftPpp*!)1eQ0j z8AldQVzniR&{WE82pr3^hN8z(#L~pBVwU&5vVH=aA-%v^f`m8dWUqSRl!f8nqMgrU zWrMa1J%rW@K~h(H^5W_agUOXWJu)dam}!~v#TOH#6HVpdz$T-U_&Dx~>W_3TMZr+H zXhMt1)-&e!JQS5xpFRy6cdt=H7vm$rzPaD;UP#G?^qi4;5m9$ZuH7z$c?nxiFI(L3 z$y1F9#Ft(QwN{7$MX4jRT2~wO0%!zv1d}fD4Py z1`|Q{$1hG|G4gV3MsAsz9e^7mIkPoV7vrn{*roO(G5$E9nD7Ylg33Z{+z(~dGBLfk z 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