Set the color space to sRGB on the Surface and remove colorFilter.
Also for a canvas wrapping a bitmap the colorspace of the bitmap will be used to correctly blend content. Test: CtsUiRenderingTestCases Bug: 111436479 Change-Id: I63ad7a30605a7f725cc0ef4716d42ea978fb03e3
This commit is contained in:
@@ -64,11 +64,10 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j
|
||||
jint tileModeX, jint tileModeY) {
|
||||
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
|
||||
sk_sp<SkImage> image;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
if (jbitmap) {
|
||||
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
|
||||
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
|
||||
image = android::bitmap::toBitmap(env, jbitmap).makeImage(&colorFilter);
|
||||
image = android::bitmap::toBitmap(env, jbitmap).makeImage();
|
||||
}
|
||||
|
||||
if (!image.get()) {
|
||||
@@ -81,9 +80,6 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j
|
||||
if (matrix) {
|
||||
shader = shader->makeWithLocalMatrix(*matrix);
|
||||
}
|
||||
if(colorFilter) {
|
||||
shader = shader->makeWithColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
ThrowIAE_IfNull(env, shader.get());
|
||||
return reinterpret_cast<jlong>(shader.release());
|
||||
|
||||
@@ -85,19 +85,18 @@ void DeferredLayerUpdater::apply() {
|
||||
mUpdateTexImage = false;
|
||||
sk_sp<SkImage> layerImage;
|
||||
SkMatrix textureTransform;
|
||||
android_dataspace dataSpace;
|
||||
bool queueEmpty = true;
|
||||
// If the SurfaceTexture queue is in synchronous mode, need to discard all
|
||||
// but latest frame. Since we can't tell which mode it is in,
|
||||
// do this unconditionally.
|
||||
do {
|
||||
layerImage = mSurfaceTexture->dequeueImage(textureTransform, dataSpace, &queueEmpty,
|
||||
layerImage = mSurfaceTexture->dequeueImage(textureTransform, &queueEmpty,
|
||||
mRenderState);
|
||||
} while (layerImage.get() && (!queueEmpty));
|
||||
if (layerImage.get()) {
|
||||
// force filtration if buffer size != layer size
|
||||
bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
|
||||
updateLayer(forceFilter, textureTransform, dataSpace, layerImage);
|
||||
updateLayer(forceFilter, textureTransform, layerImage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,12 +108,11 @@ void DeferredLayerUpdater::apply() {
|
||||
}
|
||||
|
||||
void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
|
||||
android_dataspace dataspace, const sk_sp<SkImage>& layerImage) {
|
||||
const sk_sp<SkImage>& layerImage) {
|
||||
mLayer->setBlend(mBlend);
|
||||
mLayer->setForceFilter(forceFilter);
|
||||
mLayer->setSize(mWidth, mHeight);
|
||||
mLayer->getTexTransform() = textureTransform;
|
||||
mLayer->setDataSpace(dataspace);
|
||||
mLayer->setImage(layerImage);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
void detachSurfaceTexture();
|
||||
|
||||
void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
|
||||
android_dataspace dataspace, const sk_sp<SkImage>& layerImage);
|
||||
const sk_sp<SkImage>& layerImage);
|
||||
|
||||
void destroyLayer();
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ Layer::Layer(RenderState& renderState, sk_sp<SkColorFilter> colorFilter, int alp
|
||||
// TODO: This is a violation of Android's typical ref counting, but it
|
||||
// preserves the old inc/dec ref locations. This should be changed...
|
||||
incStrong(nullptr);
|
||||
buildColorSpaceWithFilter();
|
||||
renderState.registerLayer(this);
|
||||
texTransform.setIdentity();
|
||||
transform.setIdentity();
|
||||
@@ -43,36 +42,6 @@ Layer::~Layer() {
|
||||
mRenderState.unregisterLayer(this);
|
||||
}
|
||||
|
||||
void Layer::setColorFilter(sk_sp<SkColorFilter> filter) {
|
||||
if (filter != mColorFilter) {
|
||||
mColorFilter = filter;
|
||||
buildColorSpaceWithFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::setDataSpace(android_dataspace dataspace) {
|
||||
if (dataspace != mCurrentDataspace) {
|
||||
mCurrentDataspace = dataspace;
|
||||
buildColorSpaceWithFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::buildColorSpaceWithFilter() {
|
||||
sk_sp<SkColorFilter> colorSpaceFilter;
|
||||
sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(mCurrentDataspace);
|
||||
if (colorSpace && !colorSpace->isSRGB()) {
|
||||
colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
|
||||
}
|
||||
|
||||
if (mColorFilter && colorSpaceFilter) {
|
||||
mColorSpaceWithFilter = mColorFilter->makeComposed(colorSpaceFilter);
|
||||
} else if (colorSpaceFilter) {
|
||||
mColorSpaceWithFilter = colorSpaceFilter;
|
||||
} else {
|
||||
mColorSpaceWithFilter = mColorFilter;
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::postDecStrong() {
|
||||
mRenderState.postDecStrong(this);
|
||||
}
|
||||
|
||||
@@ -69,15 +69,9 @@ public:
|
||||
|
||||
SkBlendMode getMode() const;
|
||||
|
||||
inline SkColorFilter* getColorFilter() const { return mColorFilter.get(); }
|
||||
inline sk_sp<SkColorFilter> getColorFilter() const { return mColorFilter; }
|
||||
|
||||
void setColorFilter(sk_sp<SkColorFilter> filter);
|
||||
|
||||
void setDataSpace(android_dataspace dataspace);
|
||||
|
||||
void setColorSpace(sk_sp<SkColorSpace> colorSpace);
|
||||
|
||||
inline sk_sp<SkColorFilter> getColorSpaceWithFilter() const { return mColorSpaceWithFilter; }
|
||||
void setColorFilter(sk_sp<SkColorFilter> filter) { mColorFilter = filter; };
|
||||
|
||||
inline SkMatrix& getTexTransform() { return texTransform; }
|
||||
|
||||
@@ -98,23 +92,11 @@ protected:
|
||||
RenderState& mRenderState;
|
||||
|
||||
private:
|
||||
void buildColorSpaceWithFilter();
|
||||
|
||||
/**
|
||||
* Color filter used to draw this layer. Optional.
|
||||
*/
|
||||
sk_sp<SkColorFilter> mColorFilter;
|
||||
|
||||
/**
|
||||
* Colorspace of the contents of the layer. Optional.
|
||||
*/
|
||||
android_dataspace mCurrentDataspace = HAL_DATASPACE_UNKNOWN;
|
||||
|
||||
/**
|
||||
* A color filter that is the combination of the mColorFilter and mColorSpace. Optional.
|
||||
*/
|
||||
sk_sp<SkColorFilter> mColorSpaceWithFilter;
|
||||
|
||||
/**
|
||||
* Indicates raster data backing the layer is scaled, requiring filtration.
|
||||
*/
|
||||
|
||||
@@ -66,13 +66,10 @@ CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBi
|
||||
|
||||
sk_sp<SkColorSpace> colorSpace =
|
||||
DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace()));
|
||||
sk_sp<SkColorFilter> colorSpaceFilter;
|
||||
if (colorSpace && !colorSpace->isSRGB()) {
|
||||
colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
|
||||
}
|
||||
sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
|
||||
reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType);
|
||||
return copyImageInto(image, colorSpaceFilter, texTransform, srcRect, bitmap);
|
||||
reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()),
|
||||
kPremul_SkAlphaType, colorSpace);
|
||||
return copyImageInto(image, texTransform, srcRect, bitmap);
|
||||
}
|
||||
|
||||
CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
|
||||
@@ -83,20 +80,7 @@ CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
|
||||
transform.loadScale(1, -1, 1);
|
||||
transform.translate(0, -1);
|
||||
|
||||
// TODO: Try to take and reuse the image inside HW bitmap with "hwBitmap->makeImage".
|
||||
// TODO: When this was attempted, it resulted in instability.
|
||||
sk_sp<SkColorFilter> colorSpaceFilter;
|
||||
sk_sp<SkColorSpace> colorSpace = hwBitmap->info().refColorSpace();
|
||||
if (colorSpace && !colorSpace->isSRGB()) {
|
||||
colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
|
||||
}
|
||||
sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
|
||||
reinterpret_cast<AHardwareBuffer*>(hwBitmap->graphicBuffer()), kPremul_SkAlphaType);
|
||||
|
||||
// HW Bitmap currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888 format
|
||||
// and SRGB color space. ImageDecoder can create a new HW Bitmap with non-SRGB color space: for
|
||||
// example see android.graphics.cts.BitmapColorSpaceTest#testEncodeP3hardware test.
|
||||
return copyImageInto(image, colorSpaceFilter, transform, srcRect, bitmap);
|
||||
return copyImageInto(hwBitmap->makeImage(), transform, srcRect, bitmap);
|
||||
}
|
||||
|
||||
CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
|
||||
@@ -118,8 +102,7 @@ CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap
|
||||
return copyResult;
|
||||
}
|
||||
|
||||
CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
|
||||
sk_sp<SkColorFilter>& colorSpaceFilter, Matrix4& texTransform,
|
||||
CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
|
||||
const Rect& srcRect, SkBitmap* bitmap) {
|
||||
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
|
||||
mRenderThread.requireGlContext();
|
||||
@@ -157,11 +140,7 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
|
||||
return copyResult;
|
||||
}
|
||||
|
||||
// See Readback::copyLayerInto for an overview of color space conversion.
|
||||
// HW Bitmap are allowed to be in a non-SRGB color space (for example coming from ImageDecoder).
|
||||
// For Surface and HW Bitmap readback flows we pass colorSpaceFilter, which does the conversion.
|
||||
// TextureView readback is using Layer::setDataSpace, which creates a SkColorFilter internally.
|
||||
Layer layer(mRenderThread.renderState(), colorSpaceFilter, 255, SkBlendMode::kSrc);
|
||||
Layer layer(mRenderThread.renderState(), nullptr, 255, SkBlendMode::kSrc);
|
||||
bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width()) &&
|
||||
MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
|
||||
layer.setForceFilter(!disableFilter);
|
||||
@@ -177,38 +156,6 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
|
||||
|
||||
bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
|
||||
SkBitmap* bitmap) {
|
||||
/*
|
||||
* In the past only TextureView readback was setting the temporary surface color space to null.
|
||||
* Now all 3 readback flows are drawing into a SkSurface with null color space.
|
||||
* At readback there are 3 options to convert the source image color space to the destination
|
||||
* color space requested in "bitmap->info().colorSpace()":
|
||||
* 1. Set color space for temporary surface render target to null (disables color management),
|
||||
* colorspace tag from source SkImage is ignored by Skia,
|
||||
* convert SkImage to SRGB at draw time with SkColorFilter/SkToSRGBColorFilter,
|
||||
* do a readback from temporary SkSurface to a temporary SRGB SkBitmap "bitmap2",
|
||||
* read back from SRGB "bitmap2" into non-SRGB "bitmap" which will do a CPU color conversion.
|
||||
*
|
||||
* 2. Set color space for temporary surface render target to SRGB (not nullptr),
|
||||
* colorspace tag on the source SkImage is used by Skia to enable conversion,
|
||||
* convert SkImage to SRGB at draw time with drawImage (no filters),
|
||||
* do a readback from temporary SkSurface, which will do a color conversion from SRGB to
|
||||
* bitmap->info().colorSpace() on the CPU.
|
||||
*
|
||||
* 3. Set color space for temporary surface render target to bitmap->info().colorSpace(),
|
||||
* colorspace tag on the source SkImage is used by Skia to enable conversion,
|
||||
* convert SkImage to bitmap->info().colorSpace() at draw time with drawImage (no filters),
|
||||
* do a readback from SkSurface, which will not do any color conversion, because
|
||||
* surface was created with the same color space as the "bitmap".
|
||||
*
|
||||
* Option 1 is used for all readback flows.
|
||||
* Options 2 and 3 are new, because skia added support for non-SRGB render targets without
|
||||
* linear blending.
|
||||
* TODO: evaluate if options 2 or 3 for color space conversion are better.
|
||||
*/
|
||||
|
||||
// drop the colorSpace from the temporary surface.
|
||||
SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
|
||||
|
||||
/* This intermediate surface is present to work around a bug in SwiftShader that
|
||||
* prevents us from reading the contents of the layer's texture directly. The
|
||||
* workaround involves first rendering that texture into an intermediate buffer and
|
||||
@@ -217,70 +164,44 @@ bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect*
|
||||
* with reading incorrect data from EGLImage backed SkImage (likely a driver bug).
|
||||
*/
|
||||
sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
|
||||
SkBudgeted::kYes, surfaceInfo);
|
||||
SkBudgeted::kYes, bitmap->info());
|
||||
|
||||
// if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
|
||||
// attempt to do the intermediate rendering step in 8888
|
||||
if (!tmpSurface.get()) {
|
||||
surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
|
||||
SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
|
||||
tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
|
||||
surfaceInfo);
|
||||
tmpInfo);
|
||||
if (!tmpSurface.get()) {
|
||||
ALOGW("Unable to readback GPU contents into the provided bitmap");
|
||||
ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
|
||||
tmpSurface->getCanvas(), layer, srcRect, dstRect,
|
||||
false)) {
|
||||
// If bitmap->info().colorSpace() is non-SRGB, convert the data from SRGB to non-SRGB on
|
||||
// CPU. We can't just pass bitmap->info() to SkSurface::readPixels, because "tmpSurface" has
|
||||
// disabled color conversion.
|
||||
SkColorSpace* destColorSpace = bitmap->info().colorSpace();
|
||||
SkBitmap tempSRGBBitmap;
|
||||
SkBitmap tmpN32Bitmap;
|
||||
SkBitmap* bitmapInSRGB;
|
||||
if (destColorSpace && !destColorSpace->isSRGB()) {
|
||||
tempSRGBBitmap.allocPixels(bitmap->info().makeColorSpace(SkColorSpace::MakeSRGB()));
|
||||
bitmapInSRGB = &tempSRGBBitmap; // Need to convert latter from SRGB to non-SRGB.
|
||||
} else {
|
||||
bitmapInSRGB = bitmap; // No need for color conversion - write directly into output.
|
||||
}
|
||||
bool success = false;
|
||||
if (!skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
|
||||
tmpSurface->getCanvas(), layer, srcRect, dstRect,
|
||||
false)) {
|
||||
ALOGW("Unable to draw content from GPU into the provided bitmap");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: does any of the readbacks below clamp F16 exSRGB?
|
||||
// Readback into a SRGB SkBitmap.
|
||||
if (tmpSurface->readPixels(bitmapInSRGB->info(), bitmapInSRGB->getPixels(),
|
||||
bitmapInSRGB->rowBytes(), 0, 0)) {
|
||||
success = true;
|
||||
} else {
|
||||
// if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
|
||||
// 8888 and then convert that into the destination format before giving up.
|
||||
SkImageInfo bitmapInfo =
|
||||
SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType(),
|
||||
SkColorSpace::MakeSRGB());
|
||||
if (tmpN32Bitmap.tryAllocPixels(bitmapInfo) &&
|
||||
tmpSurface->readPixels(bitmapInfo, tmpN32Bitmap.getPixels(),
|
||||
tmpN32Bitmap.rowBytes(), 0, 0)) {
|
||||
success = true;
|
||||
bitmapInSRGB = &tmpN32Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (bitmapInSRGB != bitmap) {
|
||||
// Convert from SRGB to non-SRGB color space if needed. Convert from N32 to
|
||||
// destination bitmap color format if needed.
|
||||
if (!bitmapInSRGB->readPixels(bitmap->info(), bitmap->getPixels(),
|
||||
bitmap->rowBytes(), 0, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bitmap->notifyPixelsChanged();
|
||||
return true;
|
||||
if (!tmpSurface->readPixels(*bitmap, 0, 0)) {
|
||||
// if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
|
||||
// 8888 and then convert that into the destination format before giving up.
|
||||
SkBitmap tmpBitmap;
|
||||
SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
|
||||
if (bitmap->info().colorType() == SkColorType::kN32_SkColorType ||
|
||||
!tmpBitmap.tryAllocPixels(tmpInfo) ||
|
||||
!tmpSurface->readPixels(tmpBitmap, 0, 0) ||
|
||||
!tmpBitmap.readPixels(bitmap->info(), bitmap->getPixels(),
|
||||
bitmap->rowBytes(), 0, 0)) {
|
||||
ALOGW("Unable to convert content into the provided bitmap");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
bitmap->notifyPixelsChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace uirenderer */
|
||||
|
||||
@@ -54,8 +54,8 @@ public:
|
||||
CopyResult copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
|
||||
|
||||
private:
|
||||
CopyResult copyImageInto(const sk_sp<SkImage>& image, sk_sp<SkColorFilter>& colorSpaceFilter,
|
||||
Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap);
|
||||
CopyResult copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
|
||||
const Rect& srcRect, SkBitmap* bitmap);
|
||||
|
||||
bool copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
|
||||
SkBitmap* bitmap);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <SkAnimatedImage.h>
|
||||
#include <SkCanvasStateUtils.h>
|
||||
#include <SkColorFilter.h>
|
||||
#include <SkColorSpaceXformCanvas.h>
|
||||
#include <SkDeque.h>
|
||||
#include <SkDrawable.h>
|
||||
#include <SkGraphics.h>
|
||||
@@ -60,19 +59,8 @@ SkiaCanvas::SkiaCanvas() {}
|
||||
SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}
|
||||
|
||||
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
|
||||
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
|
||||
mCanvasOwned =
|
||||
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
|
||||
if (cs.get() == nullptr || cs->isSRGB()) {
|
||||
mCanvas = mCanvasOwned.get();
|
||||
} else {
|
||||
/** The wrapper is needed if we are drawing into a non-sRGB destination, since
|
||||
* we need to transform all colors (not just bitmaps via filters) into the
|
||||
* destination's colorspace.
|
||||
*/
|
||||
mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
|
||||
mCanvas = mCanvasWrapper.get();
|
||||
}
|
||||
mCanvasOwned = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
|
||||
mCanvas = mCanvasOwned.get();
|
||||
}
|
||||
|
||||
SkiaCanvas::~SkiaCanvas() {}
|
||||
@@ -81,7 +69,6 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) {
|
||||
if (mCanvas != skiaCanvas) {
|
||||
mCanvas = skiaCanvas;
|
||||
mCanvasOwned.reset();
|
||||
mCanvasWrapper.reset();
|
||||
}
|
||||
mSaveStack.reset(nullptr);
|
||||
}
|
||||
@@ -91,18 +78,9 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
|
||||
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
|
||||
std::unique_ptr<SkCanvas> newCanvas =
|
||||
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
|
||||
std::unique_ptr<SkCanvas> newCanvasWrapper;
|
||||
if (cs.get() != nullptr && !cs->isSRGB()) {
|
||||
newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
|
||||
}
|
||||
|
||||
// deletes the previously owned canvas (if any)
|
||||
mCanvasOwned = std::move(newCanvas);
|
||||
mCanvasWrapper = std::move(newCanvasWrapper);
|
||||
mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();
|
||||
mCanvasOwned.reset(new SkCanvas(bitmap));
|
||||
mCanvas = mCanvasOwned.get();
|
||||
|
||||
// clean up the old save stack
|
||||
mSaveStack.reset(nullptr);
|
||||
@@ -547,40 +525,14 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons
|
||||
// Canvas draw operations: Bitmaps
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter) const {
|
||||
/* We don't apply the colorSpace filter if this canvas is already wrapped with
|
||||
* a SkColorSpaceXformCanvas since it already takes care of converting the
|
||||
* contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
|
||||
* should only be used if this canvas is backed by a surface/bitmap that is known
|
||||
* to have a non-sRGB colorspace.
|
||||
*/
|
||||
if (!mCanvasWrapper && colorSpaceFilter) {
|
||||
SkPaint& tmpPaint = paint.writeable();
|
||||
if (tmpPaint.getColorFilter()) {
|
||||
tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(),
|
||||
std::move(colorSpaceFilter)));
|
||||
LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
|
||||
} else {
|
||||
tmpPaint.setColorFilter(std::move(colorSpaceFilter));
|
||||
}
|
||||
}
|
||||
return filterPaint(std::move(paint));
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
|
||||
mCanvas->drawImage(bitmap.makeImage(), left, top, filterPaint(paint));
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
|
||||
SkAutoCanvasRestore acr(mCanvas, true);
|
||||
mCanvas->concat(matrix);
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
|
||||
mCanvas->drawImage(bitmap.makeImage(), 0, 0, filterPaint(paint));
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
|
||||
@@ -589,9 +541,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s
|
||||
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
|
||||
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
|
||||
mCanvas->drawImageRect(bitmap.makeImage(), srcRect, dstRect, filterPaint(paint),
|
||||
SkCanvas::kFast_SrcRectConstraint);
|
||||
}
|
||||
|
||||
@@ -673,13 +623,9 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
|
||||
PaintCoW paintCoW(paint);
|
||||
SkPaint& tmpPaint = paintCoW.writeable();
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
sk_sp<SkShader> shader =
|
||||
image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
|
||||
if (colorFilter) {
|
||||
shader = shader->makeWithColorFilter(std::move(colorFilter));
|
||||
}
|
||||
tmpPaint.setShader(std::move(shader));
|
||||
|
||||
mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate,
|
||||
@@ -710,10 +656,7 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa
|
||||
lattice.fBounds = nullptr;
|
||||
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mCanvas->drawImageLattice(image.get(), lattice, dst,
|
||||
filterBitmap(paint, std::move(colorFilter)));
|
||||
mCanvas->drawImageLattice(bitmap.makeImage().get(), lattice, dst, filterPaint(paint));
|
||||
}
|
||||
|
||||
double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
|
||||
|
||||
@@ -232,7 +232,6 @@ private:
|
||||
|
||||
class Clip;
|
||||
|
||||
std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
|
||||
std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
|
||||
SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us
|
||||
// unless it is the same as mCanvasOwned.get()
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <SkCanvas.h>
|
||||
#include <SkImagePriv.h>
|
||||
#include <SkToSRGBColorFilter.h>
|
||||
|
||||
#include <SkHighContrastFilter.h>
|
||||
#include <limits>
|
||||
@@ -287,14 +286,8 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) {
|
||||
|
||||
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
|
||||
if (isHardware()) {
|
||||
outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
|
||||
info().colorType(), info().alphaType(), nullptr));
|
||||
outBitmap->allocPixels(mInfo);
|
||||
uirenderer::renderthread::RenderProxy::copyHWBitmapInto(this, outBitmap);
|
||||
if (mInfo.colorSpace()) {
|
||||
sk_sp<SkPixelRef> pixelRef = sk_ref_sp(outBitmap->pixelRef());
|
||||
outBitmap->setInfo(mInfo);
|
||||
outBitmap->setPixelRef(std::move(pixelRef), 0, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
outBitmap->setInfo(mInfo, rowBytes());
|
||||
@@ -313,7 +306,7 @@ GraphicBuffer* Bitmap::graphicBuffer() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) {
|
||||
sk_sp<SkImage> Bitmap::makeImage() {
|
||||
sk_sp<SkImage> image = mImage;
|
||||
if (!image) {
|
||||
SkASSERT(!isHardware());
|
||||
@@ -325,9 +318,6 @@ sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) {
|
||||
// TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
|
||||
image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
|
||||
}
|
||||
if (image->colorSpace() != nullptr && !image->colorSpace()->isSRGB()) {
|
||||
*outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace());
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,14 +105,8 @@ public:
|
||||
* Creates or returns a cached SkImage and is safe to be invoked from either
|
||||
* the UI or RenderThread.
|
||||
*
|
||||
* @param outputColorFilter is a required param that will be populated by
|
||||
* this function if the bitmap's colorspace is not sRGB. If populated the
|
||||
* filter will convert colors from the bitmaps colorspace into sRGB. It
|
||||
* is the callers responsibility to use this colorFilter when drawing
|
||||
* this image into any destination that is presumed to be sRGB (i.e. a
|
||||
* buffer that has no colorspace defined).
|
||||
*/
|
||||
sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter);
|
||||
sk_sp<SkImage> makeImage();
|
||||
|
||||
static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes);
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
|
||||
SkPaint paint;
|
||||
paint.setAlpha(layer->getAlpha());
|
||||
paint.setBlendMode(layer->getMode());
|
||||
paint.setColorFilter(layer->getColorSpaceWithFilter());
|
||||
paint.setColorFilter(layer->getColorFilter());
|
||||
const bool nonIdentityMatrix = !matrix.isIdentity();
|
||||
if (nonIdentityMatrix) {
|
||||
canvas->save();
|
||||
|
||||
@@ -97,7 +97,7 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
|
||||
SkASSERT(mRenderThread.getGrContext() != nullptr);
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
|
||||
mRenderThread.getGrContext(), backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
|
||||
nullptr, &props));
|
||||
mSurfaceColorSpace, &props));
|
||||
|
||||
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
|
||||
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
|
||||
@@ -172,6 +172,7 @@ bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
|
||||
} else if (colorMode == ColorMode::WideColorGamut) {
|
||||
mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
|
||||
}
|
||||
mSurfaceColorSpace = SkColorSpace::MakeSRGB();
|
||||
|
||||
if (mEglSurface != EGL_NO_SURFACE) {
|
||||
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
|
||||
|
||||
@@ -169,7 +169,7 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator
|
||||
if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
|
||||
SkImageInfo info;
|
||||
info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
|
||||
kPremul_SkAlphaType);
|
||||
kPremul_SkAlphaType, getSurfaceColorSpace());
|
||||
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
|
||||
SkASSERT(mRenderThread.getGrContext() != nullptr);
|
||||
node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
|
||||
@@ -204,8 +204,7 @@ void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
|
||||
GrContext* context = thread.getGrContext();
|
||||
if (context) {
|
||||
ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
auto image = bitmap->makeImage(&colorFilter);
|
||||
auto image = bitmap->makeImage();
|
||||
if (image.get() && !bitmap->isHardware()) {
|
||||
SkImage_pinAsTexture(image.get(), context);
|
||||
SkImage_unpinAsTexture(image.get(), context);
|
||||
|
||||
@@ -179,9 +179,8 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
|
||||
}
|
||||
|
||||
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)), bitmap.palette());
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
mRecorder.drawImage(image, left, top, filterPaint(paint), bitmap.palette());
|
||||
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
|
||||
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
|
||||
// when this function ends.
|
||||
@@ -194,9 +193,8 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con
|
||||
SkAutoCanvasRestore acr(&mRecorder, true);
|
||||
concat(matrix);
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)), bitmap.palette());
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
mRecorder.drawImage(image, 0, 0, filterPaint(paint), bitmap.palette());
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
|
||||
mDisplayList->mMutableImages.push_back(image.get());
|
||||
}
|
||||
@@ -208,9 +206,8 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
|
||||
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
|
||||
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
mRecorder.drawImageRect(image, srcRect, dstRect, filterPaint(paint),
|
||||
SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
|
||||
!dstRect.isEmpty()) {
|
||||
@@ -247,10 +244,9 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
|
||||
if (!filteredPaint || filteredPaint->getFilterQuality() != kLow_SkFilterQuality) {
|
||||
filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
|
||||
}
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
mRecorder.drawImageLattice(image, lattice, dst,
|
||||
filterBitmap(std::move(filteredPaint), std::move(colorFilter)),
|
||||
filterPaint(std::move(filteredPaint)),
|
||||
bitmap.palette());
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
|
||||
mDisplayList->mMutableImages.push_back(image.get());
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "renderthread/EglManager.h"
|
||||
#include "renderthread/RenderThread.h"
|
||||
#include "renderthread/VulkanManager.h"
|
||||
#include "utils/Color.h"
|
||||
|
||||
// Macro for including the SurfaceTexture name in log messages
|
||||
#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
|
||||
@@ -44,13 +45,16 @@ void ImageConsumer::onReleaseBufferLocked(int buf) {
|
||||
mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
|
||||
}
|
||||
|
||||
void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer) {
|
||||
if (!mImage.get()) {
|
||||
void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
|
||||
android_dataspace dataspace) {
|
||||
if (!mImage.get() || dataspace != mDataspace) {
|
||||
mImage = graphicBuffer.get()
|
||||
? SkImage::MakeFromAHardwareBuffer(
|
||||
reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
|
||||
kPremul_SkAlphaType)
|
||||
kPremul_SkAlphaType,
|
||||
uirenderer::DataSpaceToColorSpace(dataspace))
|
||||
: nullptr;
|
||||
mDataspace = dataspace;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +70,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
|
||||
int slot = st.mCurrentTexture;
|
||||
if (slot != BufferItem::INVALID_BUFFER_SLOT) {
|
||||
*queueEmpty = true;
|
||||
mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
|
||||
mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
|
||||
return mImageSlots[slot].mImage;
|
||||
}
|
||||
}
|
||||
@@ -145,7 +149,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
|
||||
st.computeCurrentTransformMatrixLocked();
|
||||
|
||||
*queueEmpty = false;
|
||||
mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
|
||||
mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
|
||||
return mImageSlots[slot].mImage;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,18 +68,21 @@ private:
|
||||
* ImageConsumer maintains about a BufferQueue buffer slot.
|
||||
*/
|
||||
struct ImageSlot {
|
||||
ImageSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
|
||||
ImageSlot() : mDataspace(HAL_DATASPACE_UNKNOWN), mEglFence(EGL_NO_SYNC_KHR) {}
|
||||
|
||||
// mImage is the SkImage created from mGraphicBuffer.
|
||||
sk_sp<SkImage> mImage;
|
||||
|
||||
// the dataspace associated with the current image
|
||||
android_dataspace mDataspace;
|
||||
|
||||
/**
|
||||
* mEglFence is the EGL sync object that must signal before the buffer
|
||||
* associated with this buffer slot may be dequeued.
|
||||
*/
|
||||
EGLSyncKHR mEglFence;
|
||||
|
||||
void createIfNeeded(sp<GraphicBuffer> graphicBuffer);
|
||||
void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -470,8 +470,7 @@ void SurfaceTexture::dumpLocked(String8& result, const char* prefix) const {
|
||||
ConsumerBase::dumpLocked(result, prefix);
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
|
||||
bool* queueEmpty,
|
||||
sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, bool* queueEmpty,
|
||||
uirenderer::RenderState& renderState) {
|
||||
Mutex::Autolock _l(mMutex);
|
||||
|
||||
@@ -488,7 +487,6 @@ sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, android_d
|
||||
auto image = mImageConsumer.dequeueImage(queueEmpty, *this, renderState);
|
||||
if (image.get()) {
|
||||
uirenderer::mat4(mCurrentTransformMatrix).copyTo(transformMatrix);
|
||||
dataSpace = mCurrentDataSpace;
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -258,8 +258,8 @@ public:
|
||||
*/
|
||||
status_t attachToContext(uint32_t tex);
|
||||
|
||||
sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
|
||||
bool* queueEmpty, uirenderer::RenderState& renderState);
|
||||
sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, bool* queueEmpty,
|
||||
uirenderer::RenderState& renderState);
|
||||
|
||||
/**
|
||||
* attachToView attaches a SurfaceTexture that is currently in the
|
||||
|
||||
@@ -72,9 +72,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
|
||||
layerUpdater->setTransform(&transform);
|
||||
|
||||
// updateLayer so it's ready to draw
|
||||
SkMatrix identity;
|
||||
identity.setIdentity();
|
||||
layerUpdater->updateLayer(true, identity, HAL_DATASPACE_UNKNOWN, nullptr);
|
||||
layerUpdater->updateLayer(true, SkMatrix::I(), nullptr);
|
||||
return layerUpdater;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,7 @@ public:
|
||||
});
|
||||
|
||||
SkPaint paint;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = hwuiBitmap->makeImage(&colorFilter);
|
||||
sk_sp<SkImage> image = hwuiBitmap->makeImage();
|
||||
sk_sp<SkShader> repeatShader =
|
||||
image->makeShader(SkShader::TileMode::kRepeat_TileMode,
|
||||
SkShader::TileMode::kRepeat_TileMode, nullptr);
|
||||
|
||||
@@ -72,8 +72,7 @@ public:
|
||||
void doFrame(int frameNr) override {}
|
||||
|
||||
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
return image->makeShader(SkShader::TileMode::kClamp_TileMode,
|
||||
SkShader::TileMode::kClamp_TileMode);
|
||||
}
|
||||
|
||||
@@ -54,8 +54,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
|
||||
// create an image and pin it so that we have something with a unique key in the cache
|
||||
sk_sp<Bitmap> bitmap =
|
||||
Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(displayInfo.w, displayInfo.h));
|
||||
sk_sp<SkColorFilter> filter;
|
||||
sk_sp<SkImage> image = bitmap->makeImage(&filter);
|
||||
sk_sp<SkImage> image = bitmap->makeImage();
|
||||
ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
|
||||
|
||||
// attempt to trim all memory while we still hold strong refs
|
||||
|
||||
@@ -43,7 +43,7 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) {
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocN32Pixels(16, 16);
|
||||
sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
|
||||
layerUpdater->updateLayer(true, scaledMatrix, HAL_DATASPACE_UNKNOWN, layerImage);
|
||||
layerUpdater->updateLayer(true, scaledMatrix, layerImage);
|
||||
|
||||
// the backing layer should now have all the properties applied.
|
||||
EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
|
||||
|
||||
@@ -53,12 +53,12 @@ TEST(SkiaCanvas, colorSpaceXform) {
|
||||
adobeBitmap->getSkBitmap(&adobeSkBitmap);
|
||||
*adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0; // Opaque, almost fully-red
|
||||
|
||||
SkImageInfo info = adobeInfo.makeColorSpace(nullptr);
|
||||
SkImageInfo info = adobeInfo.makeColorSpace(SkColorSpace::MakeSRGB());
|
||||
sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
|
||||
SkBitmap skBitmap;
|
||||
bitmap->getSkBitmap(&skBitmap);
|
||||
|
||||
// Create a software canvas.
|
||||
// Create a software sRGB canvas.
|
||||
SkiaCanvas canvas(skBitmap);
|
||||
canvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
|
||||
// The result should be fully red, since we convert to sRGB at draw time.
|
||||
@@ -77,7 +77,7 @@ TEST(SkiaCanvas, colorSpaceXform) {
|
||||
picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
|
||||
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
|
||||
|
||||
// Playback to an software canvas. The result should be fully red.
|
||||
// Playback to a software sRGB canvas. The result should be fully red.
|
||||
canvas.asSkCanvas()->drawPicture(picture);
|
||||
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user