summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt36
-rw-r--r--api/system-current.txt36
-rw-r--r--api/test-current.txt36
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp77
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp7
-rw-r--r--core/jni/android/graphics/Graphics.cpp19
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h2
-rw-r--r--core/jni/android_view_GraphicBuffer.cpp4
-rw-r--r--core/jni/android_view_Surface.cpp4
-rw-r--r--core/jni/android_view_SurfaceControl.cpp10
-rw-r--r--core/jni/android_view_TextureView.cpp8
-rw-r--r--docs/html/reference/images/graphics/colorspace_ucs.pngbin0 -> 291374 bytes
-rw-r--r--graphics/java/android/graphics/Bitmap.java43
-rw-r--r--graphics/java/android/graphics/ColorSpace.java214
-rw-r--r--graphics/java/android/graphics/PixelFormat.java32
-rw-r--r--libs/hwui/OpenGLReadback.cpp7
-rw-r--r--libs/hwui/Texture.cpp6
-rw-r--r--libs/hwui/hwui/Bitmap.cpp5
18 files changed, 412 insertions, 134 deletions
diff --git a/api/current.txt b/api/current.txt
index cec2b9fc2457..89573ace6dac 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11769,6 +11769,8 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
+ method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
@@ -11833,6 +11835,7 @@ package android.graphics {
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
+ enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12192,6 +12195,7 @@ package android.graphics {
method public android.graphics.Bitmap render();
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
method public android.graphics.ColorSpace.Renderer size(int);
+ method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
}
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
@@ -12727,7 +12731,9 @@ package android.graphics {
field public static final deprecated int RGBA_4444 = 7; // 0x7
field public static final deprecated int RGBA_5551 = 6; // 0x6
field public static final int RGBA_8888 = 1; // 0x1
+ field public static final int RGBA_F16 = 22; // 0x16
field public static final int RGBX_8888 = 2; // 0x2
+ field public static final int RGBX_F16 = 23; // 0x17
field public static final deprecated int RGB_332 = 11; // 0xb
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
@@ -61421,31 +61427,31 @@ package java.util.concurrent {
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
diff --git a/api/system-current.txt b/api/system-current.txt
index b0236ea15fc2..7d8da95f0b37 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -12262,6 +12262,8 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
+ method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
@@ -12326,6 +12328,7 @@ package android.graphics {
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
+ enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12685,6 +12688,7 @@ package android.graphics {
method public android.graphics.Bitmap render();
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
method public android.graphics.ColorSpace.Renderer size(int);
+ method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
}
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
@@ -13220,7 +13224,9 @@ package android.graphics {
field public static final deprecated int RGBA_4444 = 7; // 0x7
field public static final deprecated int RGBA_5551 = 6; // 0x6
field public static final int RGBA_8888 = 1; // 0x1
+ field public static final int RGBA_F16 = 22; // 0x16
field public static final int RGBX_8888 = 2; // 0x2
+ field public static final int RGBX_F16 = 23; // 0x17
field public static final deprecated int RGB_332 = 11; // 0xb
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
@@ -64923,31 +64929,31 @@ package java.util.concurrent {
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
diff --git a/api/test-current.txt b/api/test-current.txt
index c798b5e165cd..251a353d2832 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -11800,6 +11800,8 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
+ method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
@@ -11864,6 +11866,7 @@ package android.graphics {
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
+ enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12223,6 +12226,7 @@ package android.graphics {
method public android.graphics.Bitmap render();
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
method public android.graphics.ColorSpace.Renderer size(int);
+ method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
}
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
@@ -12758,7 +12762,9 @@ package android.graphics {
field public static final deprecated int RGBA_4444 = 7; // 0x7
field public static final deprecated int RGBA_5551 = 6; // 0x6
field public static final int RGBA_8888 = 1; // 0x1
+ field public static final int RGBA_F16 = 22; // 0x16
field public static final int RGBX_8888 = 2; // 0x2
+ field public static final int RGBX_F16 = 23; // 0x17
field public static final deprecated int RGB_332 = 11; // 0xb
field public static final int RGB_565 = 4; // 0x4
field public static final int RGB_888 = 3; // 0x3
@@ -61710,31 +61716,31 @@ package java.util.concurrent {
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 673cf863391c..b656bb08cba9 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -5,7 +5,11 @@
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
+#include "SkColor.h"
#include "SkColorPriv.h"
+#include "SkHalf.h"
+#include "SkPM4f.h"
+#include "SkPM4fPriv.h"
#include "GraphicsJNI.h"
#include "SkDither.h"
#include "SkUnPreMultiply.h"
@@ -232,6 +236,28 @@ using namespace android::bitmap;
typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
int x, int y);
+static void FromColor_F16(void* dst, const SkColor src[], int width,
+ int, int) {
+ uint64_t* d = (uint64_t*)dst;
+
+ for (int i = 0; i < width; i++) {
+ *d++ = SkColor4f::FromColor(*src++).premul().toF16();
+ }
+}
+
+static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
+ int, int) {
+ uint64_t* d = (uint64_t*)dst;
+
+ for (int i = 0; i < width; i++) {
+ const float* color = SkColor4f::FromColor(*src++).vec();
+ uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
+ for (int i = 0; i < 4; ++i) {
+ scratch[i] = SkFloatToHalf(color[i]);
+ }
+ }
+}
+
static void FromColor_D32(void* dst, const SkColor src[], int width,
int, int) {
SkPMColor* d = (SkPMColor*)dst;
@@ -321,6 +347,8 @@ static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
return FromColor_D565;
case kAlpha_8_SkColorType:
return FromColor_DA8;
+ case kRGBA_F16_SkColorType:
+ return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
default:
break;
}
@@ -351,8 +379,7 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int
dstBitmap.notifyPixelsChanged();
- env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
- JNI_ABORT);
+ env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
return true;
}
@@ -361,6 +388,24 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int
typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
SkColorTable*);
+static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ uint64_t* s = (uint64_t*)src;
+ do {
+ *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
+ } while (--width != 0);
+}
+
+static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ uint64_t* s = (uint64_t*)src;
+ do {
+ *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
+ } while (--width != 0);
+}
+
static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
@@ -520,6 +565,17 @@ static ToColorProc ChooseToColorProc(const SkBitmap& src) {
}
case kAlpha_8_SkColorType:
return ToColor_SA8;
+ case kRGBA_F16_SkColorType:
+ switch (src.alphaType()) {
+ case kOpaque_SkAlphaType:
+ return ToColor_F16_Raw;
+ case kPremul_SkAlphaType:
+ return ToColor_F16_Alpha;
+ case kUnpremul_SkAlphaType:
+ return ToColor_F16_Raw;
+ default:
+ return NULL;
+ }
default:
break;
}
@@ -554,7 +610,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
- GraphicsJNI::defaultColorSpace()));
+ GraphicsJNI::colorSpaceForType(colorType)));
sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
if (!nativeBitmap) {
@@ -562,8 +618,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
if (jColors != NULL) {
- GraphicsJNI::SetPixels(env, jColors, offset, stride,
- 0, 0, width, height, bitmap);
+ GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
}
return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
@@ -790,6 +845,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
const int density = p->readInt32();
if (kN32_SkColorType != colorType &&
+ kRGBA_F16_SkColorType != colorType &&
kRGB_565_SkColorType != colorType &&
kARGB_4444_SkColorType != colorType &&
kIndex_8_SkColorType != colorType &&
@@ -800,8 +856,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
- if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
- isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
+ sk_sp<SkColorSpace> colorSpace;
+ if (kRGBA_F16_SkColorType == colorType) {
+ colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
+ } else {
+ colorSpace = isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr;
+ }
+
+ if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
+ rowBytes)) {
return NULL;
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 18ed0ed72190..69c705494932 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -283,8 +283,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
// Create the codec.
NinePatchPeeker peeker;
- std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(),
- &peeker));
+ std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(
+ streamDeleter.release(), &peeker));
if (!codec.get()) {
return nullObjectReturn("SkAndroidCodec::NewFromStream returned null");
}
@@ -399,7 +399,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
// We always decode to sRGB, but only mark the bitmap with a color space if linear
// blending is enabled.
- SkImageInfo bitmapInfo = decodeInfo.makeColorSpace(GraphicsJNI::defaultColorSpace());
+ SkImageInfo bitmapInfo = decodeInfo.makeColorSpace(
+ GraphicsJNI::colorSpaceForType(decodeColorType));
if (decodeColorType == kGray_8_SkColorType) {
// The legacy implementation of BitmapFactory used kAlpha8 for
// grayscale images (before kGray8 existed). While the codec
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index d8984d336746..6f97c600a1cc 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -297,13 +297,16 @@ enum LegacyBitmapConfig {
kRGB_565_LegacyBitmapConfig = 3,
kARGB_4444_LegacyBitmapConfig = 4,
kARGB_8888_LegacyBitmapConfig = 5,
- kHardware_LegacyBitmapConfig = 6,
+ kRGBA_16F_LegacyBitmapConfig = 6,
+ kHardware_LegacyBitmapConfig = 7,
kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
};
jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
switch (colorType) {
+ case kRGBA_F16_SkColorType:
+ return kRGBA_16F_LegacyBitmapConfig;
case kN32_SkColorType:
return kARGB_8888_LegacyBitmapConfig;
case kARGB_4444_SkColorType:
@@ -329,6 +332,7 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
kRGB_565_SkColorType,
kARGB_4444_SkColorType,
kN32_SkColorType,
+ kRGBA_F16_SkColorType,
kN32_SkColorType
};
@@ -458,6 +462,19 @@ sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
#endif
}
+sk_sp<SkColorSpace> GraphicsJNI::linearColorSpace() {
+ return SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
+}
+
+sk_sp<SkColorSpace> GraphicsJNI::colorSpaceForType(SkColorType type) {
+ switch (type) {
+ case kRGBA_F16_SkColorType:
+ return linearColorSpace();
+ default:
+ return defaultColorSpace();
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 03dc1fbe82fa..508c9ffd0f20 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -95,6 +95,8 @@ public:
const SkBitmap& dstBitmap);
static sk_sp<SkColorSpace> defaultColorSpace();
+ static sk_sp<SkColorSpace> linearColorSpace();
+ static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
};
class HeapAllocator : public SkBRDAllocator {
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index b6b524597896..bb69e27933b2 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -142,6 +142,10 @@ static inline SkColorType convertPixelFormat(int32_t format) {
return kN32_SkColorType;
case PIXEL_FORMAT_RGBX_8888:
return kN32_SkColorType;
+ case PIXEL_FORMAT_RGBA_FP16:
+ return kRGBA_F16_SkColorType;
+ case PIXEL_FORMAT_RGBX_FP16:
+ return kRGBA_F16_SkColorType;
case PIXEL_FORMAT_RGB_565:
return kRGB_565_SkColorType;
default:
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 92693b710424..a5b7671fa1ac 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -168,6 +168,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
switch(format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_RGBX_FP16:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_Y8:
@@ -283,6 +285,8 @@ static inline SkColorType convertPixelFormat(PixelFormat format) {
switch (format) {
case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
+ case PIXEL_FORMAT_RGBX_FP16: return kRGBA_F16_SkColorType;
+ case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType;
case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
default: return kUnknown_SkColorType;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5b8818171b6f..62c3d04f117b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -164,6 +164,16 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
alphaType = kPremul_SkAlphaType;
break;
}
+ case PIXEL_FORMAT_RGBX_FP16: {
+ colorType = kRGBA_F16_SkColorType;
+ alphaType = kOpaque_SkAlphaType;
+ break;
+ }
+ case PIXEL_FORMAT_RGBA_FP16: {
+ colorType = kRGBA_F16_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
+ }
case PIXEL_FORMAT_RGB_565: {
colorType = kRGB_565_SkColorType;
alphaType = kOpaque_SkAlphaType;
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 3c8db7fd3c3d..d3c020215485 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -83,6 +83,14 @@ static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer)
colorType = kN32_SkColorType;
alphaType = kOpaque_SkAlphaType;
break;
+ case WINDOW_FORMAT_RGBA_FP16:
+ colorType = kRGBA_F16_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
+ case WINDOW_FORMAT_RGBX_FP16:
+ colorType = kRGBA_F16_SkColorType;
+ alphaType = kOpaque_SkAlphaType;
+ break;
case WINDOW_FORMAT_RGB_565:
colorType = kRGB_565_SkColorType;
alphaType = kOpaque_SkAlphaType;
diff --git a/docs/html/reference/images/graphics/colorspace_ucs.png b/docs/html/reference/images/graphics/colorspace_ucs.png
new file mode 100644
index 000000000000..3e0f0c6f0cc4
--- /dev/null
+++ b/docs/html/reference/images/graphics/colorspace_ucs.png
Binary files differ
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index cd75fe95121a..a041a28010e2 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -140,7 +140,7 @@ public final class Bitmap implements Parcelable {
* Native bitmap has been reconfigured, so set premult and cached
* width/height values
*/
- // called from JNI
+ @SuppressWarnings("unused") // called from JNI
void reinit(int width, int height, boolean requestPremultiplied) {
mWidth = width;
mHeight = height;
@@ -465,6 +465,15 @@ public final class Bitmap implements Parcelable {
*/
ARGB_8888 (5),
+ /**
+ * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
+ * for translucency) is stored as a
+ * {@link android.util.Half half-precision floating point value}.
+ *
+ * This configuration is particularly suited for wide-gamut and
+ * HDR content.
+ */
+ RGBA_F16 (6),
/**
* Special configuration, when bitmap is stored only in graphic memory.
@@ -473,12 +482,12 @@ public final class Bitmap implements Parcelable {
* It is optimal for cases, when the only operation with the bitmap is to draw it on a
* screen.
*/
- HARDWARE (6);
+ HARDWARE (7);
final int nativeInt;
private static Config sConfigs[] = {
- null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, HARDWARE
+ null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
};
Config(int ni) {
@@ -760,6 +769,9 @@ public final class Bitmap implements Parcelable {
case ALPHA_8:
newConfig = Config.ALPHA_8;
break;
+ case RGBA_F16:
+ newConfig = Config.RGBA_F16;
+ break;
//noinspection deprecation
case ARGB_4444:
case ARGB_8888:
@@ -781,8 +793,13 @@ public final class Bitmap implements Parcelable {
neww = Math.round(deviceR.width());
newh = Math.round(deviceR.height());
- bitmap = createBitmap(neww, newh, transformed ? Config.ARGB_8888 : newConfig,
- transformed || source.hasAlpha());
+ Config transformedConfig = newConfig;
+ if (transformed) {
+ if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
+ transformedConfig = Config.ARGB_8888;
+ }
+ }
+ bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());
canvas.translate(-deviceR.left, -deviceR.top);
canvas.concat(m);
@@ -845,14 +862,14 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
- * bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
+ * mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
- private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
+ public static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
return createBitmap(null, width, height, config, hasAlpha);
}
@@ -865,14 +882,14 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
- * bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
+ * mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
- private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
+ public static Bitmap createBitmap(DisplayMetrics display, int width, int height,
Config config, boolean hasAlpha) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
@@ -885,7 +902,7 @@ public final class Bitmap implements Parcelable {
bm.mDensity = display.densityDpi;
}
bm.setHasAlpha(hasAlpha);
- if (config == Config.ARGB_8888 && !hasAlpha) {
+ if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) {
nativeErase(bm.mNativePtr, 0xff000000);
}
// No need to initialize the bitmap to zeroes with other configs;
@@ -1526,7 +1543,7 @@ public final class Bitmap implements Parcelable {
/**
* <p>Replace pixels in the bitmap with the colors in the array. Each element
- * in the array is a packed int prepresenting a non-premultiplied ARGB
+ * in the array is a packed int representing a non-premultiplied ARGB
* {@link Color}.</p>
*
* @param pixels The colors to write to the bitmap
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 7dc5de3051e6..d968516f36bc 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1671,6 +1671,28 @@ public abstract class ColorSpace {
}
/**
+ * Converts values from CIE xyY to CIE L*u*v*. Y is assumed to be 1 so the
+ * input xyY array only contains the x and y components. After this method
+ * returns, the xyY array contains the converted u and v components.
+ *
+ * @param xyY The xyY value to convert to XYZ, cannot be null,
+ * length must be a multiple of 2
+ */
+ private static void xyYToUv(@NonNull @Size(multiple = 2) float[] xyY) {
+ for (int i = 0; i < xyY.length; i += 2) {
+ float x = xyY[i];
+ float y = xyY[i + 1];
+
+ float d = -2.0f * x + 12.0f * y + 3;
+ float u = (4.0f * x) / d;
+ float v = (9.0f * y) / d;
+
+ xyY[i] = u;
+ xyY[i + 1] = v;
+ }
+ }
+
+ /**
* <p>Computes the chromatic adaptation transform from the specified
* source white point to the specified destination white point.</p>
*
@@ -3162,10 +3184,10 @@ public abstract class ColorSpace {
/**
* <p>A color space renderer can be used to visualize and compare the gamut and
* white point of one or more color spaces. The output is an sRGB {@link Bitmap}
- * showing a CIE 1931 xyY chromaticity diagram.</p>
+ * showing a CIE 1931 xyY or a CIE 1976 UCS chromaticity diagram.</p>
*
* <p>The following code snippet shows how to compare the {@link Named#SRGB}
- * and {@link Named#DCI_P3} color spaces:</p>
+ * and {@link Named#DCI_P3} color spaces in a CIE 1931 diagram:</p>
*
* <pre class="prettyprint">
* Bitmap bitmap = ColorSpace.createRenderer()
@@ -3188,12 +3210,18 @@ public abstract class ColorSpace {
*/
public static class Renderer {
private static final int NATIVE_SIZE = 1440;
+ private static final float UCS_SCALE = 9.0f / 6.0f;
+
+ // Number of subdivision of the inside of the spectral locus
+ private static final int CHROMATICITY_RESOLUTION = 32;
+ private static final double ONE_THIRD = 1.0 / 3.0;
@IntRange(from = 128, to = Integer.MAX_VALUE)
private int mSize = 1024;
private boolean mShowWhitePoint = true;
private boolean mClip = false;
+ private boolean mUcs = false;
private final List<Pair<ColorSpace, Integer>> mColorSpaces = new ArrayList<>(2);
private final List<Point> mPoints = new ArrayList<>(0);
@@ -3241,6 +3269,35 @@ public abstract class ColorSpace {
}
/**
+ * <p>Defines whether the chromaticity diagram should use the uniform
+ * chromaticity scale (CIE 1976 UCS). When the uniform chromaticity scale
+ * is used, the distance between two points on the diagram is approximately
+ * proportional to the perceived color difference.</p>
+ *
+ * <p>The following code snippet shows how to enable the uniform chromaticity
+ * scale. The image below shows the result:</p>
+ * <pre class="prettyprint">
+ * Bitmap bitmap = ColorSpace.createRenderer()
+ * .uniformChromaticityScale(true)
+ * .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff)
+ * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845)
+ * .render();
+ * </pre>
+ * <p>
+ * <img src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
+ * <figcaption style="text-align: center;">CIE 1976 UCS diagram</figcaption>
+ * </p>
+ *
+ * @param ucs True to render the chromaticity diagram as the CIE 1976 UCS diagram
+ * @return This instance of {@link Renderer}
+ */
+ @NonNull
+ public Renderer uniformChromaticityScale(boolean ucs) {
+ mUcs = ucs;
+ return this;
+ }
+
+ /**
* Sets the dimensions (width and height) in pixels of the output bitmap.
* The size must be at least 128px and defaults to 1024px.
*
@@ -3302,7 +3359,7 @@ public abstract class ColorSpace {
* </pre>
* <p>
* <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
- * <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
+ * <figcaption style="text-align: center;">sRGB, DCI-P3, ACES and scRGB</figcaption>
* </p>
*
* @param colorSpace The color space whose gamut to render on the diagram
@@ -3385,6 +3442,7 @@ public abstract class ColorSpace {
setTransform(canvas, width, height, primaries);
drawBox(canvas, width, height, paint, path);
+ setUcsTransform(canvas, height);
drawLocus(canvas, width, height, paint, path, primaries);
drawGamuts(canvas, width, height, paint, path, primaries, whitePoint);
drawPoints(canvas, width, height, paint);
@@ -3406,7 +3464,11 @@ public abstract class ColorSpace {
paint.setStyle(Paint.Style.FILL);
+ float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f);
+
float[] v = new float[3];
+ float[] xy = new float[2];
+
for (final Point point : mPoints) {
v[0] = point.mRgb[0];
v[1] = point.mRgb[1];
@@ -3415,10 +3477,13 @@ public abstract class ColorSpace {
paint.setColor(point.mColor);
- // XYZ to xyY, assuming Y=1.0
+ // XYZ to xyY, assuming Y=1.0, then to L*u*v* if needed
float sum = v[0] + v[1] + v[2];
- canvas.drawCircle(width * v[0] / sum, height - height * v[1] / sum,
- 4.0f, paint);
+ xy[0] = v[0] / sum;
+ xy[1] = v[1] / sum;
+ if (mUcs) xyYToUv(xy);
+
+ canvas.drawCircle(width * xy[0], height - height * xy[1], radius, paint);
}
}
@@ -3440,6 +3505,8 @@ public abstract class ColorSpace {
@NonNull Paint paint, @NonNull Path path,
@NonNull @Size(6) float[] primaries, @NonNull @Size(2) float[] whitePoint) {
+ float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f);
+
for (final Pair<ColorSpace, Integer> item : mColorSpaces) {
ColorSpace colorSpace = item.first;
int color = item.second;
@@ -3447,7 +3514,7 @@ public abstract class ColorSpace {
if (colorSpace.getModel() != Model.RGB) continue;
Rgb rgb = (Rgb) colorSpace;
- getPrimaries(rgb, primaries);
+ getPrimaries(rgb, primaries, mUcs);
path.rewind();
path.moveTo(width * primaries[0], height - height * primaries[1]);
@@ -3462,11 +3529,12 @@ public abstract class ColorSpace {
// Draw the white point
if (mShowWhitePoint) {
rgb.getWhitePoint(whitePoint);
+ if (mUcs) xyYToUv(whitePoint);
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
- canvas.drawCircle(width * whitePoint[0], height - height * whitePoint[1],
- 4.0f, paint);
+ canvas.drawCircle(
+ width * whitePoint[0], height - height * whitePoint[1], radius, paint);
}
}
}
@@ -3477,10 +3545,12 @@ public abstract class ColorSpace {
*
* @param rgb The color space whose primaries to extract
* @param primaries A pre-allocated array of 6 floats that will hold the result
+ * @param asUcs True if the primaries should be returned in Luv, false for xyY
*/
@NonNull
@Size(6)
- private static float[] getPrimaries(@NonNull Rgb rgb, @NonNull @Size(6) float[] primaries) {
+ private static float[] getPrimaries(@NonNull Rgb rgb,
+ @NonNull @Size(6) float[] primaries, boolean asUcs) {
// TODO: We should find a better way to handle these cases
if (rgb.equals(ColorSpace.get(Named.EXTENDED_SRGB)) ||
rgb.equals(ColorSpace.get(Named.LINEAR_EXTENDED_SRGB))) {
@@ -3490,9 +3560,11 @@ public abstract class ColorSpace {
primaries[3] = 1.24f;
primaries[4] = -0.23f;
primaries[5] = -0.57f;
- return primaries;
+ } else {
+ rgb.getPrimaries(primaries);
}
- return rgb.getPrimaries(primaries);
+ if (asUcs) xyYToUv(primaries);
+ return primaries;
}
/**
@@ -3513,7 +3585,13 @@ public abstract class ColorSpace {
int vertexCount = SPECTRUM_LOCUS_X.length * CHROMATICITY_RESOLUTION * 6;
float[] vertices = new float[vertexCount * 2];
int[] colors = new int[vertices.length];
- computeChromaticityMesh(NATIVE_SIZE, NATIVE_SIZE, vertices, colors);
+ computeChromaticityMesh(vertices, colors);
+
+ if (mUcs) xyYToUv(vertices);
+ for (int i = 0; i < vertices.length; i += 2) {
+ vertices[i] *= width;
+ vertices[i + 1] = height - vertices[i + 1] * height;
+ }
// Draw the spectral locus
if (mClip && mColorSpaces.size() > 0) {
@@ -3522,7 +3600,8 @@ public abstract class ColorSpace {
if (colorSpace.getModel() != Model.RGB) continue;
Rgb rgb = (Rgb) colorSpace;
- getPrimaries(rgb, primaries);
+ getPrimaries(rgb, primaries, mUcs);
+
break;
}
@@ -3559,6 +3638,7 @@ public abstract class ColorSpace {
}
path.close();
+ paint.setStrokeWidth(4.0f / (mUcs ? UCS_SCALE : 1.0f));
paint.setStyle(Paint.Style.STROKE);
paint.setColor(0xff000000);
canvas.drawPath(path, paint);
@@ -3576,25 +3656,38 @@ public abstract class ColorSpace {
*/
private void drawBox(@NonNull Canvas canvas, int width, int height, @NonNull Paint paint,
@NonNull Path path) {
+
+ int lineCount = 10;
+ float scale = 1.0f;
+ if (mUcs) {
+ lineCount = 7;
+ scale = UCS_SCALE;
+ }
+
// Draw the unit grid
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2.0f);
paint.setColor(0xffc0c0c0);
- for (int i = 1; i <= 9; i++) {
- canvas.drawLine(0.0f, height - (height * i / 10.0f),
- 0.9f * width, height - (height * i / 10.0f), paint);
- canvas.drawLine(width * i / 10.0f, height,
- width * i / 10.0f, 0.1f * height, paint);
+
+ for (int i = 1; i < lineCount - 1; i++) {
+ float v = i / 10.0f;
+ float x = (width * v) * scale;
+ float y = height - (height * v) * scale;
+
+ canvas.drawLine(0.0f, y, 0.9f * width, y, paint);
+ canvas.drawLine(x, height, x, 0.1f * height, paint);
}
// Draw tick marks
paint.setStrokeWidth(4.0f);
paint.setColor(0xff000000);
- for (int i = 1; i <= 9; i++) {
- canvas.drawLine(0.0f, height - (height * i / 10.0f),
- width / 100.0f, height - (height * i / 10.0f), paint);
- canvas.drawLine(width * i / 10.0f, height,
- width * i / 10.0f, height - (height / 100.0f), paint);
+ for (int i = 1; i < lineCount - 1; i++) {
+ float v = i / 10.0f;
+ float x = (width * v) * scale;
+ float y = height - (height * v) * scale;
+
+ canvas.drawLine(0.0f, y, width / 100.0f, y, paint);
+ canvas.drawLine(x, height, x, height - (height / 100.0f), paint);
}
// Draw the axis labels
@@ -3603,14 +3696,15 @@ public abstract class ColorSpace {
paint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
Rect bounds = new Rect();
- for (int i = 1; i < 9; i++) {
+ for (int i = 1; i < lineCount - 1; i++) {
String text = "0." + i;
paint.getTextBounds(text, 0, text.length(), bounds);
- float y = height - (height * i / 10.0f);
- canvas.drawText(text, -0.05f * width + 10, y + bounds.height() / 2.0f, paint);
+ float v = i / 10.0f;
+ float x = (width * v) * scale;
+ float y = height - (height * v) * scale;
- float x = width * i / 10.0f;
+ canvas.drawText(text, -0.05f * width + 10, y + bounds.height() / 2.0f, paint);
canvas.drawText(text, x - bounds.width() / 2.0f,
height + bounds.height() + 16, paint);
}
@@ -3643,7 +3737,7 @@ public abstract class ColorSpace {
if (colorSpace.getModel() != Model.RGB) continue;
Rgb rgb = (Rgb) colorSpace;
- getPrimaries(rgb, primaries);
+ getPrimaries(rgb, primaries, mUcs);
primariesBounds.left = Math.min(primariesBounds.left, primaries[4]);
primariesBounds.top = Math.min(primariesBounds.top, primaries[5]);
@@ -3651,26 +3745,42 @@ public abstract class ColorSpace {
primariesBounds.bottom = Math.max(primariesBounds.bottom, primaries[3]);
}
+ float max = mUcs ? 0.6f : 0.9f;
+
primariesBounds.left = Math.min(0.0f, primariesBounds.left);
primariesBounds.top = Math.min(0.0f, primariesBounds.top);
- primariesBounds.right = Math.max(0.9f, primariesBounds.right);
- primariesBounds.bottom = Math.max(0.9f, primariesBounds.bottom);
+ primariesBounds.right = Math.max(max, primariesBounds.right);
+ primariesBounds.bottom = Math.max(max, primariesBounds.bottom);
- float scaleX = 0.9f / primariesBounds.width();
- float scaleY = 0.9f / primariesBounds.height();
+ float scaleX = max / primariesBounds.width();
+ float scaleY = max / primariesBounds.height();
float scale = Math.min(scaleX, scaleY);
canvas.scale(mSize / (float) NATIVE_SIZE, mSize / (float) NATIVE_SIZE);
canvas.scale(scale, scale);
canvas.translate(
- (primariesBounds.width() - 0.9f) * width / 2.0f,
- (primariesBounds.height() - 0.9f) * height / 2.0f);
+ (primariesBounds.width() - max) * width / 2.0f,
+ (primariesBounds.height() - max) * height / 2.0f);
// The spectrum extends ~0.85 vertically and ~0.65 horizontally
// We shift the canvas a little bit to get nicer margins
canvas.translate(0.05f * width, -0.05f * height);
}
+ /**
+ * Computes and applies the Canvas transforms required to render the CIE
+ * 197 UCS chromaticity diagram.
+ *
+ * @param canvas The canvas to transform
+ * @param height Height in pixel of the final image
+ */
+ private void setUcsTransform(@NonNull Canvas canvas, int height) {
+ if (mUcs) {
+ canvas.translate(0.0f, (height - height * UCS_SCALE));
+ canvas.scale(UCS_SCALE, UCS_SCALE);
+ }
+ }
+
// X coordinates of the spectral locus in CIE 1931
private static final float[] SPECTRUM_LOCUS_X = {
0.175596f, 0.172787f, 0.170806f, 0.170085f, 0.160343f,
@@ -3716,21 +3826,15 @@ public abstract class ColorSpace {
0.037799f, 0.029673f, 0.021547f, 0.013421f, 0.005295f
};
- // Number of subdivision of the inside of the spectral locus
- private static final int CHROMATICITY_RESOLUTION = 32;
- private static final double ONE_THIRD = 1.0 / 3.0;
-
/**
* Computes a 2D mesh representation of the CIE 1931 chromaticity
* diagram.
*
- * @param width Width in pixels of the mesh
- * @param height Height in pixels of the mesh
* @param vertices Array of floats that will hold the mesh vertices
* @param colors Array of floats that will hold the mesh colors
*/
- private static void computeChromaticityMesh(int width, int height,
- @NonNull float[] vertices, @NonNull int[] colors) {
+ private static void computeChromaticityMesh(@NonNull float[] vertices,
+ @NonNull int[] colors) {
ColorSpace colorSpace = get(Named.SRGB);
@@ -3796,18 +3900,18 @@ public abstract class ColorSpace {
colorIndex += 6;
// Flip the mesh upside down to match Canvas' coordinates system
- vertices[vertexIndex++] = v1x * width;
- vertices[vertexIndex++] = height - v1y * height;
- vertices[vertexIndex++] = v2x * width;
- vertices[vertexIndex++] = height - v2y * height;
- vertices[vertexIndex++] = v3x * width;
- vertices[vertexIndex++] = height - v3y * height;
- vertices[vertexIndex++] = v1x * width;
- vertices[vertexIndex++] = height - v1y * height;
- vertices[vertexIndex++] = v3x * width;
- vertices[vertexIndex++] = height - v3y * height;
- vertices[vertexIndex++] = v4x * width;
- vertices[vertexIndex++] = height - v4y * height;
+ vertices[vertexIndex++] = v1x;
+ vertices[vertexIndex++] = v1y;
+ vertices[vertexIndex++] = v2x;
+ vertices[vertexIndex++] = v2y;
+ vertices[vertexIndex++] = v3x;
+ vertices[vertexIndex++] = v3y;
+ vertices[vertexIndex++] = v1x;
+ vertices[vertexIndex++] = v1y;
+ vertices[vertexIndex++] = v3x;
+ vertices[vertexIndex++] = v3y;
+ vertices[vertexIndex++] = v4x;
+ vertices[vertexIndex++] = v4y;
}
}
}
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index 98082cae8379..0fa52f895dd9 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -22,13 +22,17 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class PixelFormat {
-
/** @hide */
@IntDef({UNKNOWN, TRANSLUCENT, TRANSPARENT, OPAQUE})
@Retention(RetentionPolicy.SOURCE)
public @interface Opacity {}
- /* these constants need to match those in hardware/hardware.h */
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RGBA_8888, RGBX_8888, RGBA_F16, RGBX_F16, RGB_888, RGB_565})
+ public @interface Format { };
+
+ // NOTE: these constants must match the values from graphics/common/x.x/types.hal
public static final int UNKNOWN = 0;
@@ -62,7 +66,6 @@ public class PixelFormat {
@Deprecated
public static final int RGB_332 = 0xB;
-
/**
* @deprecated use {@link android.graphics.ImageFormat#NV16
* ImageFormat.NV16} instead.
@@ -84,6 +87,9 @@ public class PixelFormat {
@Deprecated
public static final int YCbCr_422_I = 0x14;
+ public static final int RGBA_F16 = 0x16;
+ public static final int RGBX_F16 = 0x17;
+
/**
* @deprecated use {@link android.graphics.ImageFormat#JPEG
* ImageFormat.JPEG} instead.
@@ -91,7 +97,10 @@ public class PixelFormat {
@Deprecated
public static final int JPEG = 0x100;
- public static void getPixelFormatInfo(int format, PixelFormat info) {
+ public int bytesPerPixel;
+ public int bitsPerPixel;
+
+ public static void getPixelFormatInfo(@Format int format, PixelFormat info) {
switch (format) {
case RGBA_8888:
case RGBX_8888:
@@ -124,18 +133,24 @@ public class PixelFormat {
info.bitsPerPixel = 12;
info.bytesPerPixel = 1;
break;
+ case RGBA_F16:
+ case RGBX_F16:
+ info.bitsPerPixel = 64;
+ info.bytesPerPixel = 8;
+ break;
default:
throw new IllegalArgumentException("unknown pixel format " + format);
}
}
- public static boolean formatHasAlpha(int format) {
+ public static boolean formatHasAlpha(@Format int format) {
switch (format) {
case PixelFormat.A_8:
case PixelFormat.LA_88:
case PixelFormat.RGBA_4444:
case PixelFormat.RGBA_5551:
case PixelFormat.RGBA_8888:
+ case PixelFormat.RGBA_F16:
case PixelFormat.TRANSLUCENT:
case PixelFormat.TRANSPARENT:
return true;
@@ -143,9 +158,6 @@ public class PixelFormat {
return false;
}
- public int bytesPerPixel;
- public int bitsPerPixel;
-
/**
* Determine whether or not this is a public-visible and non-deprecated {@code format}.
*
@@ -159,12 +171,14 @@ public class PixelFormat {
*
* @hide
*/
- public static boolean isPublicFormat(int format) {
+ public static boolean isPublicFormat(@Format int format) {
switch (format) {
case RGBA_8888:
case RGBX_8888:
case RGB_888:
case RGB_565:
+ case RGBA_F16:
+ case RGBX_F16:
return true;
}
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 4c8abc5da832..938b6efa7901 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -131,6 +131,13 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
destWidth, destHeight, caches.maxTextureSize);
return CopyResult::DestinationInvalid;
}
+
+ // TODO: Add support for RGBA_F16 destinations
+ if (bitmap->colorType() == kRGBA_F16_SkColorType) {
+ ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
+ return CopyResult::DestinationInvalid;
+ }
+
GLuint fbo = renderState.createFramebuffer();
if (!fbo) {
ALOGW("Could not obtain an FBO");
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 5b5b74e1c3f3..705395e1e2b7 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -225,6 +225,12 @@ void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType color
*outInternalFormat = GL_LUMINANCE;
*outType = GL_UNSIGNED_BYTE;
break;
+ case kRGBA_F16_SkColorType:
+ // This format is always linear
+ *outFormat = GL_RGBA;
+ *outInternalFormat = GL_RGBA16F;
+ *outType = GL_HALF_FLOAT;
+ break;
default:
LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
break;
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 2177af1773e5..a9058b1fb6f6 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -108,6 +108,8 @@ static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
return PIXEL_FORMAT_RGBA_8888;
case GL_RGB:
return PIXEL_FORMAT_RGB_565;
+ case GL_RGBA16F:
+ return PIXEL_FORMAT_RGBA_FP16;
default:
LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
return PIXEL_FORMAT_UNKNOWN;
@@ -306,7 +308,8 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef)
sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
PixelFormat format = graphicBuffer->getPixelFormat();
- if (!graphicBuffer.get() || format != PIXEL_FORMAT_RGBA_8888) {
+ if (!graphicBuffer.get() ||
+ (format != PIXEL_FORMAT_RGBA_8888 && format != PIXEL_FORMAT_RGBA_FP16)) {
return nullptr;
}
SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),