Reland: Widen internal API to support more complex YUV formats
Bug: skia:7901 Change-Id: Ic83e9f0c2a493335671fe431ffba6f649812d406 Reviewed-on: https://skia-review.googlesource.com/c/163481 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
2a59d8d05d
commit
8f11e43f8b
@ -495,29 +495,18 @@ static uint8_t look_up(float x1, float y1, const SkBitmap& bm, SkColorChannel c
|
||||
class YUVGenerator : public SkImageGenerator {
|
||||
public:
|
||||
YUVGenerator(const SkImageInfo& ii,
|
||||
YUVFormat yuvFormat,
|
||||
SkYUVColorSpace yuvColorSpace,
|
||||
SkYUVAIndex yuvaIndices[4],
|
||||
SkBitmap bitmaps[4])
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkBitmap bitmaps[SkYUVSizeInfo::kMaxCount])
|
||||
: SkImageGenerator(ii)
|
||||
, fYUVFormat(yuvFormat)
|
||||
, fYUVColorSpace(yuvColorSpace) {
|
||||
memcpy(fYUVAIndices, yuvaIndices, sizeof(fYUVAIndices));
|
||||
|
||||
bool used[4] = { false, false, false, false };
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (yuvaIndices[i].fIndex >= 0) {
|
||||
SkASSERT(yuvaIndices[i].fIndex < 4);
|
||||
used[yuvaIndices[i].fIndex] = true;
|
||||
} else {
|
||||
SkASSERT(3 == i); // only the 'A' channel can be unspecified
|
||||
}
|
||||
}
|
||||
SkAssertResult(SkYUVAIndex::AreValidIndices(fYUVAIndices, &fNumBitmaps));
|
||||
SkASSERT(fNumBitmaps > 0 && fNumBitmaps <= SkYUVSizeInfo::kMaxCount);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (used[i]) {
|
||||
fYUVBitmaps[i] = bitmaps[i];
|
||||
}
|
||||
for (int i = 0; i < fNumBitmaps; ++i) {
|
||||
fYUVBitmaps[i] = bitmaps[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,49 +562,53 @@ protected:
|
||||
return fFlattened.readPixels(info, pixels, rowBytes, 0, 0);
|
||||
}
|
||||
|
||||
bool onQueryYUV8(SkYUVSizeInfo* size, SkYUVColorSpace* yuvColorSpace) const override {
|
||||
if (kI420_YUVFormat != fYUVFormat && kYV12_YUVFormat != fYUVFormat) {
|
||||
return false; // currently this API only supports planar formats
|
||||
bool onQueryYUVA8(SkYUVSizeInfo* size,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* yuvColorSpace) const override {
|
||||
|
||||
memcpy(yuvaIndices, fYUVAIndices, sizeof(fYUVAIndices));
|
||||
*yuvColorSpace = fYUVColorSpace;
|
||||
|
||||
int i = 0;
|
||||
for ( ; i < fNumBitmaps; ++i) {
|
||||
size->fColorTypes[i] = fYUVBitmaps[i].colorType();
|
||||
size->fSizes[i].fWidth = fYUVBitmaps[i].width();
|
||||
size->fSizes[i].fHeight = fYUVBitmaps[i].height();
|
||||
size->fWidthBytes[i] = fYUVBitmaps[i].rowBytes();
|
||||
}
|
||||
for ( ; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
size->fColorTypes[i] = kUnknown_SkColorType;
|
||||
size->fSizes[i].fWidth = 0;
|
||||
size->fSizes[i].fHeight = 0;
|
||||
size->fWidthBytes[i] = 0;
|
||||
}
|
||||
|
||||
*yuvColorSpace = fYUVColorSpace;
|
||||
size->fSizes[0].fWidth = fYUVBitmaps[fYUVAIndices[0].fIndex].width();
|
||||
size->fSizes[0].fHeight = fYUVBitmaps[fYUVAIndices[0].fIndex].height();
|
||||
size->fWidthBytes[0] = fYUVBitmaps[fYUVAIndices[0].fIndex].rowBytes();
|
||||
|
||||
size->fSizes[1].fWidth = fYUVBitmaps[fYUVAIndices[1].fIndex].width();
|
||||
size->fSizes[1].fHeight = fYUVBitmaps[fYUVAIndices[1].fIndex].height();
|
||||
size->fWidthBytes[1] = fYUVBitmaps[fYUVAIndices[1].fIndex].rowBytes();
|
||||
|
||||
size->fSizes[2].fWidth = fYUVBitmaps[fYUVAIndices[2].fIndex].width();
|
||||
size->fSizes[2].fHeight = fYUVBitmaps[fYUVAIndices[2].fIndex].height();
|
||||
size->fWidthBytes[2] = fYUVBitmaps[fYUVAIndices[2].fIndex].rowBytes();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onGetYUV8Planes(const SkYUVSizeInfo&, void* planes[3]) override {
|
||||
planes[0] = fYUVBitmaps[fYUVAIndices[0].fIndex].getAddr(0, 0);
|
||||
planes[1] = fYUVBitmaps[fYUVAIndices[1].fIndex].getAddr(0, 0);
|
||||
planes[2] = fYUVBitmaps[fYUVAIndices[2].fIndex].getAddr(0, 0);
|
||||
bool onGetYUVA8Planes(const SkYUVSizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
|
||||
void* planes[SkYUVSizeInfo::kMaxCount]) override {
|
||||
for (int i = 0; i < fNumBitmaps; ++i) {
|
||||
planes[i] = fYUVBitmaps[i].getPixels();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
YUVFormat fYUVFormat;
|
||||
SkYUVColorSpace fYUVColorSpace;
|
||||
SkYUVAIndex fYUVAIndices[4];
|
||||
SkBitmap fYUVBitmaps[4];
|
||||
SkYUVAIndex fYUVAIndices[SkYUVAIndex::kIndexCount];
|
||||
int fNumBitmaps;
|
||||
SkBitmap fYUVBitmaps[SkYUVSizeInfo::kMaxCount];
|
||||
SkBitmap fFlattened;
|
||||
|
||||
};
|
||||
|
||||
static sk_sp<SkImage> make_yuv_gen_image(const SkImageInfo& ii,
|
||||
YUVFormat yuvFormat,
|
||||
SkYUVColorSpace yuvColorSpace,
|
||||
SkYUVAIndex yuvaIndices[4],
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkBitmap bitmaps[]) {
|
||||
std::unique_ptr<SkImageGenerator> gen(new YUVGenerator(ii, yuvFormat, yuvColorSpace,
|
||||
yuvaIndices, bitmaps));
|
||||
std::unique_ptr<SkImageGenerator> gen(new YUVGenerator(ii, yuvColorSpace,
|
||||
yuvaIndices, bitmaps));
|
||||
|
||||
return SkImage::MakeFromGenerator(std::move(gen));
|
||||
}
|
||||
@ -774,7 +767,6 @@ protected:
|
||||
{
|
||||
fImages[opaque][cs][format] = make_yuv_gen_image(
|
||||
fOriginalBMs[opaque].info(),
|
||||
(YUVFormat) format,
|
||||
(SkYUVColorSpace) cs,
|
||||
yuvaIndices,
|
||||
resultBMs);
|
||||
|
@ -327,6 +327,7 @@ skia_core_sources = [
|
||||
"$_src/core/SkXfermodeInterpretation.h",
|
||||
"$_src/core/SkYUVPlanesCache.cpp",
|
||||
"$_src/core/SkYUVPlanesCache.h",
|
||||
"$_src/core/SkYUVSizeInfo.cpp",
|
||||
|
||||
"$_src/image/SkImage.cpp",
|
||||
|
||||
@ -419,6 +420,7 @@ skia_core_sources = [
|
||||
"$_include/core/SkUnPreMultiply.h",
|
||||
"$_include/core/SkVertices.h",
|
||||
"$_include/core/SkYUVAIndex.h",
|
||||
"$_include/core/SkYUVSizeInfo.h",
|
||||
|
||||
"$_src/jumper/SkJumper.cpp",
|
||||
|
||||
|
@ -351,7 +351,9 @@ public:
|
||||
* returns false and does not modify any of the parameters.
|
||||
*
|
||||
* @param sizeInfo Output parameter indicating the sizes and required
|
||||
* allocation widths of the Y, U, and V planes.
|
||||
* allocation widths of the Y, U, V, and A planes. Given current codec
|
||||
* limitations the size of the A plane will always be 0 and the Y, U, V
|
||||
* channels will always be planar.
|
||||
* @param colorSpace Output parameter. If non-NULL this is set to kJPEG,
|
||||
* otherwise this is ignored.
|
||||
*/
|
||||
@ -360,7 +362,19 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->onQueryYUV8(sizeInfo, colorSpace);
|
||||
bool result = this->onQueryYUV8(sizeInfo, colorSpace);
|
||||
if (result) {
|
||||
for (int i = 0; i <= 2; ++i) {
|
||||
SkASSERT(kAlpha_8_SkColorType == sizeInfo->fColorTypes[i]);
|
||||
SkASSERT(sizeInfo->fSizes[i].fWidth > 0 && sizeInfo->fSizes[i].fHeight > 0 &&
|
||||
sizeInfo->fWidthBytes[i] > 0);
|
||||
}
|
||||
SkASSERT(kUnknown_SkColorType == sizeInfo->fColorTypes[3]);
|
||||
SkASSERT(!sizeInfo->fSizes[3].fWidth &&
|
||||
!sizeInfo->fSizes[3].fHeight &&
|
||||
!sizeInfo->fWidthBytes[3]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -373,11 +387,12 @@ public:
|
||||
* recommendation (but not smaller).
|
||||
* @param planes Memory for each of the Y, U, and V planes.
|
||||
*/
|
||||
Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
|
||||
if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
|
||||
nullptr == planes[2]) {
|
||||
Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[SkYUVSizeInfo::kMaxCount]) {
|
||||
if (!planes || !planes[0] || !planes[1] || !planes[2]) {
|
||||
return kInvalidInput;
|
||||
}
|
||||
SkASSERT(kUnknown_SkColorType == sizeInfo.fColorTypes[3]);
|
||||
SkASSERT(!planes[3]); // TODO: is this a fair assumption?
|
||||
|
||||
if (!this->rewindIfNeeded()) {
|
||||
return kCouldNotRewind;
|
||||
@ -712,7 +727,8 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
|
||||
virtual Result onGetYUV8Planes(const SkYUVSizeInfo&,
|
||||
void*[SkYUVSizeInfo::kMaxCount] /*planes*/) {
|
||||
return kUnimplemented;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ class SkCanvas;
|
||||
class SkImage;
|
||||
class SkSurface;
|
||||
struct SkYUVAIndex;
|
||||
struct SkYUVSizeInfo;
|
||||
|
||||
/*
|
||||
* This class is intended to be used as:
|
||||
@ -125,7 +126,7 @@ public:
|
||||
*/
|
||||
sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
|
||||
const GrBackendFormat yuvaFormats[],
|
||||
const SkISize yuvaSizes[],
|
||||
const SkYUVSizeInfo& yuvaSizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[4],
|
||||
int imageWidth,
|
||||
int imageHeight,
|
||||
@ -136,7 +137,7 @@ public:
|
||||
PromiseDoneProc promiseDoneProc,
|
||||
TextureContext textureContexts[]);
|
||||
|
||||
// deprecated version that doesn't take yuvaSizes
|
||||
// deprecated version that doesn't take yuvaSizeInfo
|
||||
sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
|
||||
const GrBackendFormat yuvaFormats[],
|
||||
const SkYUVAIndex yuvaIndices[4],
|
||||
|
@ -86,23 +86,30 @@ public:
|
||||
* If decoding to YUV is supported, this returns true. Otherwise, this
|
||||
* returns false and does not modify any of the parameters.
|
||||
*
|
||||
* @param sizeInfo Output parameter indicating the sizes and required
|
||||
* allocation widths of the Y, U, and V planes.
|
||||
* @param colorSpace Output parameter.
|
||||
* @param sizeInfo Output parameter indicating the sizes and required
|
||||
* allocation widths of the Y, U, V, and A planes.
|
||||
* @param yuvaIndices How the YUVA planes are organized/used
|
||||
* @param colorSpace Output parameter.
|
||||
*/
|
||||
bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const;
|
||||
bool queryYUVA8(SkYUVSizeInfo* sizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace) const;
|
||||
|
||||
/**
|
||||
* Returns true on success and false on failure.
|
||||
* This always attempts to perform a full decode. If the client only
|
||||
* wants size, it should call queryYUV8().
|
||||
* wants size, it should call queryYUVA8().
|
||||
*
|
||||
* @param sizeInfo Needs to exactly match the values returned by the
|
||||
* query, except the WidthBytes may be larger than the
|
||||
* recommendation (but not smaller).
|
||||
* @param planes Memory for each of the Y, U, and V planes.
|
||||
* @param sizeInfo Needs to exactly match the values returned by the
|
||||
* query, except the WidthBytes may be larger than the
|
||||
* recommendation (but not smaller).
|
||||
* @param yuvaIndices Needs to exactly match the values returned by the query.
|
||||
* @param planes Memory for the Y, U, V, and A planes. Note that, depending on the
|
||||
* settings in yuvaIndices, anywhere from 1..4 planes could be returned.
|
||||
*/
|
||||
bool getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]);
|
||||
bool getYUVA8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
void* planes[]);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
/**
|
||||
@ -163,9 +170,13 @@ protected:
|
||||
struct Options {};
|
||||
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
|
||||
virtual bool onIsValid(GrContext*) const { return true; }
|
||||
virtual bool onQueryYUVA8(SkYUVSizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace*) const { return false; }
|
||||
virtual bool onGetYUVA8Planes(const SkYUVSizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
|
||||
void*[4] /*planes*/) { return false; }
|
||||
// Deprecated methods
|
||||
virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const { return false; }
|
||||
virtual bool onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) { return false; }
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
enum class TexGenType {
|
||||
kNone, //image generator does not implement onGenerateTexture
|
||||
|
@ -38,12 +38,16 @@ struct SK_API SkYUVAIndex {
|
||||
}
|
||||
|
||||
// Index in the array of SkYUVAIndex
|
||||
// TODO: rename as Component
|
||||
enum Index {
|
||||
kY_Index = 0,
|
||||
kU_Index = 1,
|
||||
kV_Index = 2,
|
||||
kA_Index = 3
|
||||
kA_Index = 3,
|
||||
|
||||
kLast_Index = kA_Index
|
||||
};
|
||||
static constexpr int kIndexCount = kLast_Index + 1;
|
||||
|
||||
/** The index is a number between -1..3 which definies which image source to read from, where -1
|
||||
* means the image source doesn't exist. The assumption is we will always have image sources for
|
||||
|
15
include/core/SkYUVASizeInfo.h
Normal file
15
include/core/SkYUVASizeInfo.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkYUVASizeInfo_DEFINED
|
||||
#define SkYUVASizeInfo_DEFINED
|
||||
|
||||
#include "SkYUVSizeInfo.h"
|
||||
|
||||
using SkYUVASizeInfo = SkYUVSizeInfo;
|
||||
|
||||
#endif // SkYUVASizeInfo_DEFINED
|
@ -8,18 +8,18 @@
|
||||
#ifndef SkYUVSizeInfo_DEFINED
|
||||
#define SkYUVSizeInfo_DEFINED
|
||||
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkSize.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
|
||||
struct SkYUVSizeInfo {
|
||||
enum YUVIndex {
|
||||
kY = 0,
|
||||
kU = 1,
|
||||
kV = 2,
|
||||
};
|
||||
SkISize fSizes[3];
|
||||
static constexpr auto kMaxCount = 4;
|
||||
|
||||
SkColorType fColorTypes[kMaxCount];
|
||||
SkISize fSizes[kMaxCount];
|
||||
|
||||
/**
|
||||
* While the widths of the Y, U, and V planes are not restricted, the
|
||||
* While the widths of the Y, U, V and A planes are not restricted, the
|
||||
* implementation often requires that the width of the memory allocated
|
||||
* for each plane be a multiple of 8.
|
||||
*
|
||||
@ -30,7 +30,44 @@ struct SkYUVSizeInfo {
|
||||
* include any extra padding, while, in this case, every single row of
|
||||
* the allocation must be at least "widthBytes".
|
||||
*/
|
||||
size_t fWidthBytes[3];
|
||||
size_t fWidthBytes[kMaxCount];
|
||||
|
||||
bool operator==(const SkYUVSizeInfo& that) const {
|
||||
for (int i = 0; i < kMaxCount; ++i) {
|
||||
if (fColorTypes[i] != that.fColorTypes[i]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kUnknown_SkColorType == fColorTypes[i]) {
|
||||
SkASSERT(!fSizes[i].fWidth && !fSizes[i].fHeight && !fWidthBytes[i]);
|
||||
SkASSERT(!that.fSizes[i].fWidth && !that.fSizes[i].fHeight && !that.fWidthBytes[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
SkASSERT(fSizes[i].fWidth && fSizes[i].fHeight && fWidthBytes[i]);
|
||||
if (fSizes[i] != that.fSizes[i] || fWidthBytes[i] != that.fWidthBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t computeTotalBytes() const {
|
||||
size_t totalBytes = 0;
|
||||
|
||||
for (int i = 0; i < kMaxCount; ++i) {
|
||||
SkASSERT(kUnknown_SkColorType != fColorTypes[i] ||
|
||||
(!fSizes[i].fWidth && !fSizes[i].fHeight && !fWidthBytes[i]));
|
||||
|
||||
totalBytes += fWidthBytes[i] * fSizes[i].height();
|
||||
}
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
void computePlanes(void* base, void* planes[kMaxCount]) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // SkYUVSizeInfo_DEFINED
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "SkCodecImageGenerator.h"
|
||||
#include "SkMakeUnique.h"
|
||||
#include "SkPixmapPriv.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
|
||||
std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
|
||||
auto codec = SkCodec::MakeFromData(data);
|
||||
@ -58,13 +59,27 @@ bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* re
|
||||
return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
|
||||
}
|
||||
|
||||
bool SkCodecImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const
|
||||
{
|
||||
bool SkCodecImageGenerator::onQueryYUVA8(SkYUVSizeInfo* sizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace) const {
|
||||
// This image generator always returns 3 separate non-interleaved planes
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 2;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
|
||||
|
||||
return fCodec->queryYUV8(sizeInfo, colorSpace);
|
||||
}
|
||||
|
||||
bool SkCodecImageGenerator::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
|
||||
bool SkCodecImageGenerator::onGetYUVA8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
|
||||
void* planes[]) {
|
||||
SkCodec::Result result = fCodec->getYUV8Planes(sizeInfo, planes);
|
||||
// TODO: check indices
|
||||
|
||||
switch (result) {
|
||||
case SkCodec::kSuccess:
|
||||
|
@ -22,12 +22,14 @@ public:
|
||||
protected:
|
||||
sk_sp<SkData> onRefEncodedData() override;
|
||||
|
||||
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
|
||||
override;
|
||||
bool onGetPixels(
|
||||
const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts) override;
|
||||
|
||||
bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const override;
|
||||
bool onQueryYUVA8(
|
||||
SkYUVSizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount], SkYUVColorSpace*) const override;
|
||||
|
||||
bool onGetYUV8Planes(const SkYUVSizeInfo&, void* planes[3]) override;
|
||||
bool onGetYUVA8Planes(const SkYUVSizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
|
||||
void* planes[]) override;
|
||||
|
||||
private:
|
||||
/*
|
||||
|
@ -831,11 +831,18 @@ bool SkJpegCodec::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpa
|
||||
}
|
||||
|
||||
jpeg_component_info * comp_info = dinfo->comp_info;
|
||||
for (auto i : { SkYUVSizeInfo::kY, SkYUVSizeInfo::kU, SkYUVSizeInfo::kV }) {
|
||||
for (auto i : { SkYUVAIndex::kY_Index, SkYUVAIndex::kU_Index, SkYUVAIndex::kV_Index }) {
|
||||
sizeInfo->fColorTypes[i] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fSizes[i].set(comp_info[i].downsampled_width, comp_info[i].downsampled_height);
|
||||
sizeInfo->fWidthBytes[i] = comp_info[i].width_in_blocks * DCTSIZE;
|
||||
}
|
||||
|
||||
// JPEG never has an alpha channel
|
||||
sizeInfo->fColorTypes[SkYUVAIndex::kA_Index] = kUnknown_SkColorType;
|
||||
sizeInfo->fSizes[SkYUVAIndex::kA_Index].fHeight =
|
||||
sizeInfo->fSizes[SkYUVAIndex::kA_Index].fWidth =
|
||||
sizeInfo->fWidthBytes[SkYUVAIndex::kA_Index] = 0;
|
||||
|
||||
if (colorSpace) {
|
||||
*colorSpace = kJPEG_SkYUVColorSpace;
|
||||
}
|
||||
@ -843,18 +850,22 @@ bool SkJpegCodec::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpa
|
||||
return true;
|
||||
}
|
||||
|
||||
SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
|
||||
SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
void* planes[SkYUVSizeInfo::kMaxCount]) {
|
||||
SkYUVSizeInfo defaultInfo;
|
||||
|
||||
// This will check is_yuv_supported(), so we don't need to here.
|
||||
bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr);
|
||||
if (!supportsYUV ||
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kY] != defaultInfo.fSizes[SkYUVSizeInfo::kY] ||
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kU] != defaultInfo.fSizes[SkYUVSizeInfo::kU] ||
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kV] != defaultInfo.fSizes[SkYUVSizeInfo::kV] ||
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kY] ||
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kU] ||
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kV]) {
|
||||
kAlpha_8_SkColorType != sizeInfo.fColorTypes[0] ||
|
||||
kAlpha_8_SkColorType != sizeInfo.fColorTypes[1] ||
|
||||
kAlpha_8_SkColorType != sizeInfo.fColorTypes[2] ||
|
||||
sizeInfo.fSizes[0] != defaultInfo.fSizes[0] ||
|
||||
sizeInfo.fSizes[1] != defaultInfo.fSizes[1] ||
|
||||
sizeInfo.fSizes[2] != defaultInfo.fSizes[2] ||
|
||||
sizeInfo.fWidthBytes[0] < defaultInfo.fWidthBytes[0] ||
|
||||
sizeInfo.fWidthBytes[1] < defaultInfo.fWidthBytes[1] ||
|
||||
sizeInfo.fWidthBytes[2] < defaultInfo.fWidthBytes[2]) {
|
||||
return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput);
|
||||
}
|
||||
|
||||
@ -879,9 +890,9 @@ SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void
|
||||
|
||||
// Currently, we require that the Y plane dimensions match the image dimensions
|
||||
// and that the U and V planes are the same dimensions.
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU] == sizeInfo.fSizes[SkYUVSizeInfo::kV]);
|
||||
SkASSERT((uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].width() == dinfo->output_width &&
|
||||
(uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].height() == dinfo->output_height);
|
||||
SkASSERT(sizeInfo.fSizes[1] == sizeInfo.fSizes[2]);
|
||||
SkASSERT((uint32_t) sizeInfo.fSizes[0].width() == dinfo->output_width &&
|
||||
(uint32_t) sizeInfo.fSizes[0].height() == dinfo->output_height);
|
||||
|
||||
// Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
|
||||
// a 2-D array of pixels for each of the components (Y, U, V) in the image.
|
||||
@ -898,20 +909,19 @@ SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void
|
||||
// Initialize rowptrs.
|
||||
int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
|
||||
for (int i = 0; i < numYRowsPerBlock; i++) {
|
||||
rowptrs[i] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kY],
|
||||
i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]);
|
||||
rowptrs[i] = SkTAddOffset<JSAMPLE>(planes[0], i * sizeInfo.fWidthBytes[0]);
|
||||
}
|
||||
for (int i = 0; i < DCTSIZE; i++) {
|
||||
rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kU],
|
||||
i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU]);
|
||||
rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kV],
|
||||
i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV]);
|
||||
rowptrs[i + 2 * DCTSIZE] =
|
||||
SkTAddOffset<JSAMPLE>(planes[1], i * sizeInfo.fWidthBytes[1]);
|
||||
rowptrs[i + 3 * DCTSIZE] =
|
||||
SkTAddOffset<JSAMPLE>(planes[2], i * sizeInfo.fWidthBytes[2]);
|
||||
}
|
||||
|
||||
// After each loop iteration, we will increment pointers to Y, U, and V.
|
||||
size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fWidthBytes[SkYUVSizeInfo::kY];
|
||||
size_t blockIncrementU = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU];
|
||||
size_t blockIncrementV = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV];
|
||||
size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fWidthBytes[0];
|
||||
size_t blockIncrementU = DCTSIZE * sizeInfo.fWidthBytes[1];
|
||||
size_t blockIncrementV = DCTSIZE * sizeInfo.fWidthBytes[2];
|
||||
|
||||
uint32_t numRowsPerBlock = numYRowsPerBlock;
|
||||
|
||||
@ -944,7 +954,7 @@ SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void
|
||||
// this requirement using a dummy row buffer.
|
||||
// FIXME: Should SkCodec have an extra memory buffer that can be shared among
|
||||
// all of the implementations that use temporary/garbage memory?
|
||||
SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]);
|
||||
SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fWidthBytes[SkYUVAIndex::kY_Index]);
|
||||
for (int i = remainingRows; i < numYRowsPerBlock; i++) {
|
||||
rowptrs[i] = dummyRow.get();
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ protected:
|
||||
|
||||
bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override;
|
||||
|
||||
Result onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override;
|
||||
Result onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
void* planes[SkYUVSizeInfo::kMaxCount]) override;
|
||||
|
||||
SkEncodedImageFormat onGetEncodedFormat() const override {
|
||||
return SkEncodedImageFormat::kJPEG;
|
||||
|
@ -64,6 +64,7 @@ sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
|
||||
#include "SkImage_Gpu.h"
|
||||
#include "SkImage_GpuYUVA.h"
|
||||
#include "SkSurface_Gpu.h"
|
||||
#include "SkYUVSizeInfo.h"
|
||||
|
||||
SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
|
||||
: fCharacterization(c) {
|
||||
@ -230,7 +231,7 @@ sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
|
||||
sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
|
||||
SkYUVColorSpace yuvColorSpace,
|
||||
const GrBackendFormat yuvaFormats[],
|
||||
const SkISize yuvaSizes[],
|
||||
const SkYUVSizeInfo& yuvaSizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[4],
|
||||
int imageWidth,
|
||||
int imageHeight,
|
||||
@ -247,7 +248,7 @@ sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
|
||||
return SkImage_GpuYUVA::MakePromiseYUVATexture(fContext.get(),
|
||||
yuvColorSpace,
|
||||
yuvaFormats,
|
||||
yuvaSizes,
|
||||
yuvaSizeInfo,
|
||||
yuvaIndices,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "SkImage.h"
|
||||
#include "SkImageGenerator.h"
|
||||
#include "SkNextID.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
|
||||
SkImageGenerator::SkImageGenerator(const SkImageInfo& info, uint32_t uniqueID)
|
||||
: fInfo(info)
|
||||
@ -29,28 +30,119 @@ bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t r
|
||||
return this->onGetPixels(info, pixels, rowBytes, defaultOpts);
|
||||
}
|
||||
|
||||
bool SkImageGenerator::queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
|
||||
bool SkImageGenerator::queryYUVA8(SkYUVSizeInfo* sizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace) const {
|
||||
SkASSERT(sizeInfo);
|
||||
|
||||
return this->onQueryYUV8(sizeInfo, colorSpace);
|
||||
if (!this->onQueryYUVA8(sizeInfo, yuvaIndices, colorSpace)) {
|
||||
// try the deprecated method and make a guess at the other data
|
||||
if (this->onQueryYUV8(sizeInfo, colorSpace)) {
|
||||
// take a guess at the number of planes
|
||||
int numPlanes = SkYUVSizeInfo::kMaxCount;
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (sizeInfo->fSizes[i].isEmpty()) {
|
||||
numPlanes = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!numPlanes) {
|
||||
return false;
|
||||
}
|
||||
switch (numPlanes) {
|
||||
case 1:
|
||||
// Assume 3 interleaved planes
|
||||
sizeInfo->fColorTypes[0] = kRGBA_8888_SkColorType;
|
||||
sizeInfo->fColorTypes[1] = kUnknown_SkColorType;
|
||||
sizeInfo->fColorTypes[2] = kUnknown_SkColorType;
|
||||
sizeInfo->fColorTypes[3] = kUnknown_SkColorType;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kG;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kB;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
|
||||
break;
|
||||
case 2:
|
||||
// Assume 1 Y plane and interleaved UV planes
|
||||
sizeInfo->fColorTypes[0] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[1] = kRGBA_8888_SkColorType;
|
||||
sizeInfo->fColorTypes[2] = kUnknown_SkColorType;
|
||||
sizeInfo->fColorTypes[3] = kUnknown_SkColorType;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 1;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kG;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
|
||||
break;
|
||||
case 3:
|
||||
// Assume 3 separate non-interleaved planes
|
||||
sizeInfo->fColorTypes[0] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[1] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[2] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[3] = kUnknown_SkColorType;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 2;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
// Assume 4 separate non-interleaved planes
|
||||
sizeInfo->fColorTypes[0] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[1] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[2] = kAlpha_8_SkColorType;
|
||||
sizeInfo->fColorTypes[3] = kAlpha_8_SkColorType;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
|
||||
yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
|
||||
yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 2;
|
||||
yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fIndex = 3;
|
||||
yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkImageGenerator::getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fHeight >= 0);
|
||||
SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] >=
|
||||
(size_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth);
|
||||
SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] >=
|
||||
(size_t) sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth);
|
||||
SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] >=
|
||||
(size_t) sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth);
|
||||
SkASSERT(planes && planes[0] && planes[1] && planes[2]);
|
||||
bool SkImageGenerator::getYUVA8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
void* planes[SkYUVSizeInfo::kMaxCount]) {
|
||||
|
||||
return this->onGetYUV8Planes(sizeInfo, planes);
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
SkASSERT(sizeInfo.fSizes[i].fWidth >= 0);
|
||||
SkASSERT(sizeInfo.fSizes[i].fHeight >= 0);
|
||||
SkASSERT(sizeInfo.fWidthBytes[i] >= (size_t) sizeInfo.fSizes[i].fWidth);
|
||||
}
|
||||
|
||||
int numPlanes = 0;
|
||||
SkASSERT(SkYUVAIndex::AreValidIndices(yuvaIndices, &numPlanes));
|
||||
SkASSERT(planes);
|
||||
for (int i = 0; i < numPlanes; ++i) {
|
||||
SkASSERT(planes[i]);
|
||||
}
|
||||
|
||||
if (!this->onGetYUVA8Planes(sizeInfo, yuvaIndices, planes)) {
|
||||
return this->onGetYUV8Planes(sizeInfo, planes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "SkCachedData.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
#include "SkYUVSizeInfo.h"
|
||||
|
||||
class SkResourceCache;
|
||||
@ -17,14 +18,15 @@ class SkResourceCache;
|
||||
class SkYUVPlanesCache {
|
||||
public:
|
||||
/**
|
||||
* The Info struct contains data about the 3 Y, U and V planes of memory stored
|
||||
* The Info struct contains data about the 4 Y, U, V, and A planes of memory stored
|
||||
* contiguously, in that order, as a single block of memory within SkYUVPlanesCache.
|
||||
*
|
||||
* fSizeInfo: fWidth, fHeight, and fWidthBytes of each of the Y, U, and V planes.
|
||||
* fSizeInfo: fWidth, fHeight, and fWidthBytes of each of the Y, U, V, and A planes.
|
||||
* fColorSpace: color space that will be used for the YUV -> RGB conversion.
|
||||
*/
|
||||
struct Info {
|
||||
SkYUVSizeInfo fSizeInfo;
|
||||
SkYUVAIndex fYUVAIndices[SkYUVAIndex::kIndexCount];
|
||||
SkYUVColorSpace fColorSpace;
|
||||
};
|
||||
/**
|
||||
|
23
src/core/SkYUVSizeInfo.cpp
Normal file
23
src/core/SkYUVSizeInfo.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkYUVSizeInfo.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
void SkYUVSizeInfo::computePlanes(void* base, void* planes[SkYUVSizeInfo::kMaxCount]) const {
|
||||
planes[0] = base;
|
||||
int i = 1;
|
||||
for (; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (fSizes[i].isEmpty()) {
|
||||
break;
|
||||
}
|
||||
planes[i] = SkTAddOffset<void>(planes[i - 1], fWidthBytes[i - 1] * fSizes[i - 1].height());
|
||||
}
|
||||
for (; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
planes[i] = nullptr;
|
||||
}
|
||||
}
|
@ -22,40 +22,64 @@
|
||||
#include "effects/GrYUVtoRGBEffect.h"
|
||||
|
||||
sk_sp<SkCachedData> GrYUVProvider::getPlanes(SkYUVSizeInfo* size,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace,
|
||||
const void* constPlanes[3]) {
|
||||
const void* constPlanes[SkYUVSizeInfo::kMaxCount]) {
|
||||
sk_sp<SkCachedData> data;
|
||||
SkYUVPlanesCache::Info yuvInfo;
|
||||
data.reset(SkYUVPlanesCache::FindAndRef(this->onGetID(), &yuvInfo));
|
||||
|
||||
void* planes[3];
|
||||
void* planes[SkYUVSizeInfo::kMaxCount];
|
||||
|
||||
if (data.get()) {
|
||||
planes[0] = (void*)data->data();
|
||||
planes[1] = (uint8_t*)planes[0] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
|
||||
yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
|
||||
planes[2] = (uint8_t*)planes[1] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
|
||||
yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
|
||||
planes[0] = (void*)data->data(); // we should always have at least one plane
|
||||
|
||||
for (int i = 1; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (!yuvInfo.fSizeInfo.fWidthBytes[i]) {
|
||||
SkASSERT(kUnknown_SkColorType == yuvInfo.fSizeInfo.fColorTypes[i] &&
|
||||
!yuvInfo.fSizeInfo.fWidthBytes[i] &&
|
||||
!yuvInfo.fSizeInfo.fSizes[i].fHeight);
|
||||
planes[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
planes[i] = (uint8_t*)planes[i-1] + (yuvInfo.fSizeInfo.fWidthBytes[i-1] *
|
||||
yuvInfo.fSizeInfo.fSizes[i-1].fHeight);
|
||||
}
|
||||
} else {
|
||||
// Fetch yuv plane sizes for memory allocation.
|
||||
if (!this->onQueryYUV8(&yuvInfo.fSizeInfo, &yuvInfo.fColorSpace)) {
|
||||
if (!this->onQueryYUVA8(&yuvInfo.fSizeInfo, yuvInfo.fYUVAIndices, &yuvInfo.fColorSpace)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Allocate the memory for YUV
|
||||
// Allocate the memory for YUVA
|
||||
size_t totalSize(0);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; i++) {
|
||||
SkASSERT(kUnknown_SkColorType != yuvInfo.fSizeInfo.fColorTypes[i] ||
|
||||
(!yuvInfo.fSizeInfo.fWidthBytes[i] && !yuvInfo.fSizeInfo.fSizes[i].fHeight));
|
||||
|
||||
totalSize += yuvInfo.fSizeInfo.fWidthBytes[i] * yuvInfo.fSizeInfo.fSizes[i].fHeight;
|
||||
}
|
||||
|
||||
data.reset(SkResourceCache::NewCachedData(totalSize));
|
||||
|
||||
planes[0] = data->writable_data();
|
||||
planes[1] = (uint8_t*)planes[0] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
|
||||
yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
|
||||
planes[2] = (uint8_t*)planes[1] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
|
||||
yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
|
||||
|
||||
for (int i = 1; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (!yuvInfo.fSizeInfo.fWidthBytes[i]) {
|
||||
SkASSERT(kUnknown_SkColorType == yuvInfo.fSizeInfo.fColorTypes[i] &&
|
||||
!yuvInfo.fSizeInfo.fWidthBytes[i] &&
|
||||
!yuvInfo.fSizeInfo.fSizes[i].fHeight);
|
||||
planes[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
planes[i] = (uint8_t*)planes[i-1] + (yuvInfo.fSizeInfo.fWidthBytes[i-1] *
|
||||
yuvInfo.fSizeInfo.fSizes[i-1].fHeight);
|
||||
}
|
||||
|
||||
// Get the YUV planes.
|
||||
if (!this->onGetYUV8Planes(yuvInfo.fSizeInfo, planes)) {
|
||||
if (!this->onGetYUVA8Planes(yuvInfo.fSizeInfo, yuvInfo.fYUVAIndices, planes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -64,10 +88,12 @@ sk_sp<SkCachedData> GrYUVProvider::getPlanes(SkYUVSizeInfo* size,
|
||||
}
|
||||
|
||||
*size = yuvInfo.fSizeInfo;
|
||||
memcpy(yuvaIndices, yuvInfo.fYUVAIndices, sizeof(yuvInfo.fYUVAIndices));
|
||||
*colorSpace = yuvInfo.fColorSpace;
|
||||
constPlanes[0] = planes[0];
|
||||
constPlanes[1] = planes[1];
|
||||
constPlanes[2] = planes[2];
|
||||
constPlanes[3] = planes[3];
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -81,24 +107,33 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrS
|
||||
SkColorSpace* srcColorSpace,
|
||||
SkColorSpace* dstColorSpace) {
|
||||
SkYUVSizeInfo yuvSizeInfo;
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount];
|
||||
SkYUVColorSpace yuvColorSpace;
|
||||
const void* planes[3];
|
||||
const void* planes[SkYUVSizeInfo::kMaxCount];
|
||||
|
||||
sk_sp<SkCachedData> dataStorage = this->getPlanes(&yuvSizeInfo, &yuvColorSpace, planes);
|
||||
sk_sp<SkCachedData> dataStorage = this->getPlanes(&yuvSizeInfo, yuvaIndices,
|
||||
&yuvColorSpace, planes);
|
||||
if (!dataStorage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> yuvTextureProxies[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
sk_sp<GrTextureProxy> yuvTextureProxies[SkYUVSizeInfo::kMaxCount];
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (kUnknown_SkColorType == yuvSizeInfo.fColorTypes[i]) {
|
||||
SkASSERT(!yuvSizeInfo.fSizes[i].fWidth ||
|
||||
!yuvSizeInfo.fSizes[i].fHeight ||
|
||||
!yuvSizeInfo.fWidthBytes[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
int componentWidth = yuvSizeInfo.fSizes[i].fWidth;
|
||||
int componentHeight = yuvSizeInfo.fSizes[i].fHeight;
|
||||
// If the sizes of the components are not all the same we choose to create exact-match
|
||||
// textures for the smaller ones rather than add a texture domain to the draw.
|
||||
// TODO: revisit this decision to improve texture reuse?
|
||||
SkBackingFit fit =
|
||||
(componentWidth != yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth) ||
|
||||
(componentHeight != yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight)
|
||||
(componentWidth != yuvSizeInfo.fSizes[0].fWidth) ||
|
||||
(componentHeight != yuvSizeInfo.fSizes[0].fHeight)
|
||||
? SkBackingFit::kExact : SkBackingFit::kApprox;
|
||||
|
||||
SkImageInfo imageInfo = SkImageInfo::MakeA8(componentWidth, componentHeight);
|
||||
@ -131,17 +166,8 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrS
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This code path only generates I420 (i.e., 3 separate plane) YUVs
|
||||
SkYUVAIndex yuvaIndices[4] = {
|
||||
{ 0, SkColorChannel::kA },
|
||||
{ 1, SkColorChannel::kA },
|
||||
{ 2, SkColorChannel::kA },
|
||||
{ -1, SkColorChannel::kA }, // no alpha
|
||||
};
|
||||
|
||||
GrPaint paint;
|
||||
auto yuvToRgbProcessor =
|
||||
GrYUVtoRGBEffect::Make(yuvTextureProxies, yuvaIndices, yuvColorSpace);
|
||||
auto yuvToRgbProcessor = GrYUVtoRGBEffect::Make(yuvTextureProxies, yuvaIndices, yuvColorSpace);
|
||||
paint.addColorFragmentProcessor(std::move(yuvToRgbProcessor));
|
||||
|
||||
// If the caller expects the pixels in a different color space than the one from the image,
|
||||
@ -154,8 +180,8 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrS
|
||||
}
|
||||
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
const SkRect r = SkRect::MakeIWH(yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
|
||||
yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
|
||||
const SkRect r = SkRect::MakeIWH(yuvSizeInfo.fSizes[0].fWidth,
|
||||
yuvSizeInfo.fSizes[0].fHeight);
|
||||
|
||||
renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r);
|
||||
|
||||
|
@ -17,6 +17,7 @@ struct GrSurfaceDesc;
|
||||
class GrTexture;
|
||||
class GrTextureProxy;
|
||||
class SkCachedData;
|
||||
struct SkYUVAIndex;
|
||||
|
||||
/**
|
||||
* There are at least 2 different ways to extract/retrieve YUV planar data...
|
||||
@ -43,7 +44,8 @@ public:
|
||||
SkColorSpace* srcColorSpace,
|
||||
SkColorSpace* dstColorSpace);
|
||||
|
||||
sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]);
|
||||
sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace*, const void* planes[SkYUVSizeInfo::kMaxCount]);
|
||||
|
||||
private:
|
||||
virtual uint32_t onGetID() const = 0;
|
||||
@ -54,23 +56,29 @@ private:
|
||||
* If decoding to YUV is supported, this returns true. Otherwise, this
|
||||
* returns false and does not modify any of the parameters.
|
||||
*
|
||||
* @param sizeInfo Output parameter indicating the sizes and required
|
||||
* allocation widths of the Y, U, and V planes.
|
||||
* @param colorSpace Output parameter.
|
||||
* @param sizeInfo Output parameter indicating the sizes and required
|
||||
* allocation widths of the Y, U, V, and A planes.
|
||||
* @param yuvaIndices How the YUVA planes are used/organized
|
||||
* @param colorSpace Output parameter.
|
||||
*/
|
||||
virtual bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const = 0;
|
||||
virtual bool onQueryYUVA8(SkYUVSizeInfo* sizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace) const = 0;
|
||||
|
||||
/**
|
||||
* Returns true on success and false on failure.
|
||||
* This always attempts to perform a full decode. If the client only
|
||||
* wants size, it should call onQueryYUV8().
|
||||
* wants size, it should call onQueryYUVA8().
|
||||
*
|
||||
* @param sizeInfo Needs to exactly match the values returned by the
|
||||
* query, except the WidthBytes may be larger than the
|
||||
* recommendation (but not smaller).
|
||||
* @param planes Memory for each of the Y, U, and V planes.
|
||||
* @param sizeInfo Needs to exactly match the values returned by the
|
||||
* query, except the WidthBytes may be larger than the
|
||||
* recommendation (but not smaller).
|
||||
* @param yuvaIndices How the YUVA planes are used/organized
|
||||
* @param planes Memory for each of the Y, U, V, and A planes.
|
||||
*/
|
||||
virtual bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) = 0;
|
||||
virtual bool onGetYUVA8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
void* planes[]) = 0;
|
||||
|
||||
// This is used as release callback for the YUV data that we capture in an SkImage when
|
||||
// uploading to a gpu. When the upload is complete and we release the SkImage this callback will
|
||||
|
@ -228,7 +228,8 @@ bool SkImage::asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode ) const {
|
||||
return as_IB(this)->onAsLegacyBitmap(bitmap);
|
||||
}
|
||||
|
||||
sk_sp<SkCachedData> SkImage_Base::getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*,const void*[3]) {
|
||||
sk_sp<SkCachedData> SkImage_Base::getPlanes(SkYUVSizeInfo*, SkYUVAIndex[4],
|
||||
SkYUVColorSpace*, const void*[4]) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,8 @@ public:
|
||||
|
||||
virtual sk_sp<SkImage> onMakeSubset(const SkIRect&) const = 0;
|
||||
|
||||
virtual sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]);
|
||||
virtual sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVAIndex[4],
|
||||
SkYUVColorSpace*, const void* planes[4]);
|
||||
virtual sk_sp<SkData> onRefEncoded() const { return nullptr; }
|
||||
|
||||
virtual bool onAsLegacyBitmap(SkBitmap*) const;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "GrTexture.h"
|
||||
#include "SkImage_Gpu.h"
|
||||
#include "SkImage_GpuYUVA.h"
|
||||
#include "SkYUVSizeInfo.h"
|
||||
#include "effects/GrYUVtoRGBEffect.h"
|
||||
|
||||
SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, int width, int height, uint32_t uniqueID,
|
||||
@ -182,7 +183,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
|
||||
sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context,
|
||||
SkYUVColorSpace yuvColorSpace,
|
||||
const GrBackendFormat yuvaFormats[],
|
||||
const SkISize yuvaSizes[],
|
||||
const SkYUVSizeInfo& yuvaSizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[4],
|
||||
int imageWidth,
|
||||
int imageHeight,
|
||||
@ -232,24 +233,20 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set up color types
|
||||
SkColorType texColorTypes[4] = { kUnknown_SkColorType, kUnknown_SkColorType,
|
||||
kUnknown_SkColorType, kUnknown_SkColorType };
|
||||
for (int yuvIndex = 0; yuvIndex < 4; ++yuvIndex) {
|
||||
int texIdx = yuvaIndices[yuvIndex].fIndex;
|
||||
if (texIdx < 0) {
|
||||
SkASSERT(SkYUVAIndex::kA_Index == yuvIndex);
|
||||
continue;
|
||||
}
|
||||
if (kUnknown_SkColorType == texColorTypes[texIdx]) {
|
||||
texColorTypes[texIdx] = kAlpha_8_SkColorType;
|
||||
} else {
|
||||
texColorTypes[texIdx] = kRGBA_8888_SkColorType;
|
||||
// verify sizeInfo with expected texture count
|
||||
for (int i = 0; i < numTextures; ++i) {
|
||||
if (kUnknown_SkColorType == yuvaSizeInfo.fColorTypes[i] ||
|
||||
yuvaSizeInfo.fSizes[i].isEmpty() ||
|
||||
!yuvaSizeInfo.fWidthBytes[i]) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
// If UV is interleaved, then Y will have RGBA color type
|
||||
if (kRGBA_8888_SkColorType == texColorTypes[yuvaIndices[SkYUVAIndex::kU_Index].fIndex]) {
|
||||
texColorTypes[yuvaIndices[SkYUVAIndex::kY_Index].fIndex] = kRGBA_8888_SkColorType;
|
||||
for (int i = numTextures; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (kUnknown_SkColorType != yuvaSizeInfo.fColorTypes[i] ||
|
||||
!yuvaSizeInfo.fSizes[i].isEmpty() ||
|
||||
yuvaSizeInfo.fWidthBytes[i]) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Get lazy proxies
|
||||
@ -261,9 +258,11 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context,
|
||||
GrPixelConfig fConfig;
|
||||
SkPromiseImageHelper fPromiseHelper;
|
||||
} params;
|
||||
if (!context->contextPriv().caps()->getConfigFromBackendFormat(yuvaFormats[texIdx],
|
||||
texColorTypes[texIdx],
|
||||
¶ms.fConfig)) {
|
||||
bool res = context->contextPriv().caps()->getConfigFromBackendFormat(
|
||||
yuvaFormats[texIdx],
|
||||
yuvaSizeInfo.fColorTypes[texIdx],
|
||||
¶ms.fConfig);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
params.fPromiseHelper = promiseHelpers[texIdx];
|
||||
@ -281,8 +280,8 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context,
|
||||
};
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = kNone_GrSurfaceFlags;
|
||||
desc.fWidth = yuvaSizes[texIdx].width();
|
||||
desc.fHeight = yuvaSizes[texIdx].height();
|
||||
desc.fWidth = yuvaSizeInfo.fSizes[texIdx].width();
|
||||
desc.fHeight = yuvaSizeInfo.fSizes[texIdx].height();
|
||||
desc.fConfig = params.fConfig;
|
||||
desc.fSampleCnt = 1;
|
||||
proxies[texIdx] = proxyProvider->createLazyProxy(
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "SkYUVAIndex.h"
|
||||
|
||||
class GrTexture;
|
||||
struct SkYUVSizeInfo;
|
||||
|
||||
// Wraps the 3 or 4 planes of a YUVA image for consumption by the GPU.
|
||||
// Initially any direct rendering will be done by passing the individual planes to a shader.
|
||||
@ -62,7 +63,7 @@ public:
|
||||
@param context Gpu context
|
||||
@param yuvColorSpace color range of expected YUV pixels
|
||||
@param yuvaFormats formats of promised gpu textures for each YUVA plane
|
||||
@param yuvaSizes width and height of promised gpu textures
|
||||
@param yuvaSizeInfo width, height, and colortype of promised gpu textures
|
||||
@param yuvaIndices mapping from yuv plane index to texture representing that plane
|
||||
@param width width of promised gpu texture
|
||||
@param height height of promised gpu texture
|
||||
@ -77,7 +78,7 @@ public:
|
||||
static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context,
|
||||
SkYUVColorSpace yuvColorSpace,
|
||||
const GrBackendFormat yuvaFormats[],
|
||||
const SkISize yuvaSizes[],
|
||||
const SkYUVSizeInfo& yuvaSizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[4],
|
||||
int width,
|
||||
int height,
|
||||
|
@ -355,11 +355,15 @@ public:
|
||||
|
||||
private:
|
||||
uint32_t onGetID() const override { return fGen->uniqueID(); }
|
||||
bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override {
|
||||
return fGen->queryYUV8(sizeInfo, colorSpace);
|
||||
bool onQueryYUVA8(SkYUVSizeInfo* sizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* colorSpace) const override {
|
||||
return fGen->queryYUVA8(sizeInfo, yuvaIndices, colorSpace);
|
||||
}
|
||||
bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override {
|
||||
return fGen->getYUV8Planes(sizeInfo, planes);
|
||||
bool onGetYUVA8Planes(const SkYUVSizeInfo& sizeInfo,
|
||||
const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
void* planes[]) override {
|
||||
return fGen->getYUVA8Planes(sizeInfo, yuvaIndices, planes);
|
||||
}
|
||||
|
||||
SkImageGenerator* fGen;
|
||||
@ -384,13 +388,14 @@ static void set_key_on_proxy(GrProxyProvider* proxyProvider,
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkCachedData> SkImage_Lazy::getPlanes(SkYUVSizeInfo* yuvSizeInfo,
|
||||
sk_sp<SkCachedData> SkImage_Lazy::getPlanes(SkYUVSizeInfo* yuvaSizeInfo,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace* yuvColorSpace,
|
||||
const void* planes[3]) {
|
||||
const void* planes[SkYUVSizeInfo::kMaxCount]) {
|
||||
ScopedGenerator generator(fSharedGenerator);
|
||||
Generator_GrYUVProvider provider(generator);
|
||||
|
||||
sk_sp<SkCachedData> data = provider.getPlanes(yuvSizeInfo, yuvColorSpace, planes);
|
||||
sk_sp<SkCachedData> data = provider.getPlanes(yuvaSizeInfo, yuvaIndices, yuvColorSpace, planes);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -49,7 +49,8 @@ public:
|
||||
const GrSamplerState&, SkColorSpace*,
|
||||
sk_sp<SkColorSpace>*,
|
||||
SkScalar scaleAdjust[2]) const override;
|
||||
sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]) override;
|
||||
sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVAIndex[4],
|
||||
SkYUVColorSpace*, const void* planes[4]) override;
|
||||
#endif
|
||||
sk_sp<SkData> onRefEncoded() const override;
|
||||
sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
|
||||
|
@ -7,9 +7,11 @@
|
||||
|
||||
#include "SkData.h"
|
||||
#include "SkCanvas.h"
|
||||
|
||||
#include "SkGraphics.h"
|
||||
#include "SkImageGenerator.h"
|
||||
#include "SkImageInfoPriv.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
#include "Test.h"
|
||||
|
||||
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
|
||||
@ -61,24 +63,32 @@ public:
|
||||
DEF_TEST(ImageGenerator, reporter) {
|
||||
MyImageGenerator ig;
|
||||
SkYUVSizeInfo sizeInfo;
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kY] = SkISize::Make(200, 200);
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kU] = SkISize::Make(100, 100);
|
||||
sizeInfo.fSizes[SkYUVSizeInfo::kV] = SkISize::Make( 50, 50);
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] = 0;
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] = 0;
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] = 0;
|
||||
void* planes[3] = { nullptr };
|
||||
sizeInfo.fSizes[0] = SkISize::Make(200, 200);
|
||||
sizeInfo.fSizes[1] = SkISize::Make(100, 100);
|
||||
sizeInfo.fSizes[2] = SkISize::Make( 50, 50);
|
||||
sizeInfo.fSizes[3] = SkISize::Make( 25, 25);
|
||||
sizeInfo.fWidthBytes[0] = 0;
|
||||
sizeInfo.fWidthBytes[1] = 0;
|
||||
sizeInfo.fWidthBytes[2] = 0;
|
||||
sizeInfo.fWidthBytes[3] = 0;
|
||||
void* planes[4] = { nullptr };
|
||||
SkYUVAIndex yuvaIndices[4];
|
||||
SkYUVColorSpace colorSpace;
|
||||
|
||||
// Check that the YUV decoding API does not cause any crashes
|
||||
ig.queryYUV8(&sizeInfo, nullptr);
|
||||
ig.queryYUV8(&sizeInfo, &colorSpace);
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] = 250;
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] = 250;
|
||||
sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] = 250;
|
||||
ig.queryYUVA8(&sizeInfo, yuvaIndices, nullptr);
|
||||
ig.queryYUVA8(&sizeInfo, yuvaIndices, &colorSpace);
|
||||
sizeInfo.fWidthBytes[0] = 250;
|
||||
sizeInfo.fWidthBytes[1] = 250;
|
||||
sizeInfo.fWidthBytes[2] = 250;
|
||||
sizeInfo.fWidthBytes[3] = 250;
|
||||
yuvaIndices[0] = { 0, SkColorChannel::kR };
|
||||
yuvaIndices[1] = { 1, SkColorChannel::kR };
|
||||
yuvaIndices[2] = { 2, SkColorChannel::kR };
|
||||
yuvaIndices[3] = { 3, SkColorChannel::kR };
|
||||
int dummy;
|
||||
planes[SkYUVSizeInfo::kY] = planes[SkYUVSizeInfo::kU] = planes[SkYUVSizeInfo::kV] = &dummy;
|
||||
ig.getYUV8Planes(sizeInfo, planes);
|
||||
planes[0] = planes[1] = planes[2] = planes[3] = &dummy;
|
||||
ig.getYUVA8Planes(sizeInfo, yuvaIndices, planes);
|
||||
|
||||
// Suppressed due to https://code.google.com/p/skia/issues/detail?id=4339
|
||||
if (false) {
|
||||
|
@ -32,10 +32,16 @@ DEF_TEST(YUVPlanesCache, reporter) {
|
||||
SkResourceCache cache(1024);
|
||||
|
||||
SkYUVPlanesCache::Info yuvInfo;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
yuvInfo.fSizeInfo.fSizes[i].fWidth = 20 * i;
|
||||
yuvInfo.fSizeInfo.fSizes[i].fHeight = 10 * i;
|
||||
yuvInfo.fSizeInfo.fWidthBytes[i] = 80 * i;
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; i++) {
|
||||
yuvInfo.fSizeInfo.fColorTypes[i] = kAlpha_8_SkColorType;
|
||||
yuvInfo.fSizeInfo.fSizes[i].fWidth = 20 * (i + 1);
|
||||
yuvInfo.fSizeInfo.fSizes[i].fHeight = 10 * (i + 1);
|
||||
yuvInfo.fSizeInfo.fWidthBytes[i] = 80 * (i + 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
|
||||
yuvInfo.fYUVAIndices[i].fIndex = -1;
|
||||
yuvInfo.fYUVAIndices[i].fChannel = SkColorChannel::kR;
|
||||
}
|
||||
yuvInfo.fColorSpace = kRec601_SkYUVColorSpace;
|
||||
|
||||
@ -59,14 +65,12 @@ DEF_TEST(YUVPlanesCache, reporter) {
|
||||
|
||||
REPORTER_ASSERT(reporter, data);
|
||||
REPORTER_ASSERT(reporter, data->size() == size);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fSizeInfo.fSizes[i].fWidth ==
|
||||
yuvInfoRead.fSizeInfo.fSizes[i].fWidth);
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fSizeInfo.fSizes[i].fHeight ==
|
||||
yuvInfoRead.fSizeInfo.fSizes[i].fHeight);
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fSizeInfo.fWidthBytes[i] ==
|
||||
yuvInfoRead.fSizeInfo.fWidthBytes[i]);
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fSizeInfo == yuvInfoRead.fSizeInfo);
|
||||
|
||||
for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fYUVAIndices[i] == yuvInfoRead.fYUVAIndices[i]);
|
||||
}
|
||||
|
||||
REPORTER_ASSERT(reporter, yuvInfo.fColorSpace == yuvInfoRead.fColorSpace);
|
||||
|
||||
check_data(reporter, data, 2, kInCache, kLocked);
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "Test.h"
|
||||
|
||||
static void codec_yuv(skiatest::Reporter* reporter,
|
||||
const char path[],
|
||||
SkISize expectedSizes[3]) {
|
||||
const char path[],
|
||||
SkISize expectedSizes[4]) {
|
||||
std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
|
||||
if (!stream) {
|
||||
return;
|
||||
@ -28,59 +28,59 @@ static void codec_yuv(skiatest::Reporter* reporter,
|
||||
|
||||
// Test queryYUV8()
|
||||
SkYUVSizeInfo info;
|
||||
bool success = codec->queryYUV8(nullptr, nullptr);
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
success = codec->queryYUV8(&info, nullptr);
|
||||
REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success);
|
||||
if (!success) {
|
||||
return;
|
||||
|
||||
{
|
||||
bool success = codec->queryYUV8(nullptr, nullptr);
|
||||
REPORTER_ASSERT(reporter, !success);
|
||||
success = codec->queryYUV8(&info, nullptr);
|
||||
REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
REPORTER_ASSERT(reporter, info.fSizes[i] == expectedSizes[i]);
|
||||
REPORTER_ASSERT(reporter,
|
||||
info.fWidthBytes[i] == (uint32_t) SkAlign8(info.fSizes[i].width()));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
SkYUVColorSpace colorSpace;
|
||||
bool success = codec->queryYUV8(&info, &colorSpace);
|
||||
REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
REPORTER_ASSERT(reporter, info.fSizes[i] == expectedSizes[i]);
|
||||
REPORTER_ASSERT(reporter,
|
||||
info.fWidthBytes[i] == (uint32_t) SkAlign8(info.fSizes[i].width()));
|
||||
}
|
||||
REPORTER_ASSERT(reporter, kJPEG_SkYUVColorSpace == colorSpace);
|
||||
}
|
||||
REPORTER_ASSERT(reporter,
|
||||
0 == memcmp((const void*) &info, (const void*) expectedSizes, 3 * sizeof(SkISize)));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kY] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kY].width()));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kU] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kU].width()));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kV] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kV].width()));
|
||||
SkYUVColorSpace colorSpace;
|
||||
success = codec->queryYUV8(&info, &colorSpace);
|
||||
REPORTER_ASSERT(reporter,
|
||||
0 == memcmp((const void*) &info, (const void*) expectedSizes, 3 * sizeof(SkISize)));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kY] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kY].width()));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kU] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kU].width()));
|
||||
REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kV] ==
|
||||
(uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kV].width()));
|
||||
REPORTER_ASSERT(reporter, kJPEG_SkYUVColorSpace == colorSpace);
|
||||
|
||||
// Allocate the memory for the YUV decode
|
||||
size_t totalBytes =
|
||||
info.fWidthBytes[SkYUVSizeInfo::kY] * info.fSizes[SkYUVSizeInfo::kY].height() +
|
||||
info.fWidthBytes[SkYUVSizeInfo::kU] * info.fSizes[SkYUVSizeInfo::kU].height() +
|
||||
info.fWidthBytes[SkYUVSizeInfo::kV] * info.fSizes[SkYUVSizeInfo::kV].height();
|
||||
size_t totalBytes = info.computeTotalBytes();
|
||||
|
||||
SkAutoMalloc storage(totalBytes);
|
||||
void* planes[3];
|
||||
planes[0] = storage.get();
|
||||
planes[1] = SkTAddOffset<void>(planes[0],
|
||||
info.fWidthBytes[SkYUVSizeInfo::kY] * info.fSizes[SkYUVSizeInfo::kY].height());
|
||||
planes[2] = SkTAddOffset<void>(planes[1],
|
||||
info.fWidthBytes[SkYUVSizeInfo::kU] * info.fSizes[SkYUVSizeInfo::kU].height());
|
||||
void* planes[SkYUVSizeInfo::kMaxCount];
|
||||
|
||||
info.computePlanes(storage.get(), planes);
|
||||
|
||||
// Test getYUV8Planes()
|
||||
REPORTER_ASSERT(reporter, SkCodec::kInvalidInput ==
|
||||
codec->getYUV8Planes(info, nullptr));
|
||||
REPORTER_ASSERT(reporter, SkCodec::kSuccess ==
|
||||
codec->getYUV8Planes(info, planes));
|
||||
REPORTER_ASSERT(reporter, SkCodec::kInvalidInput == codec->getYUV8Planes(info, nullptr));
|
||||
REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUV8Planes(info, planes));
|
||||
}
|
||||
|
||||
DEF_TEST(Jpeg_YUV_Codec, r) {
|
||||
SkISize sizes[3];
|
||||
SkISize sizes[4];
|
||||
|
||||
sizes[0].set(128, 128);
|
||||
sizes[1].set(64, 64);
|
||||
sizes[2].set(64, 64);
|
||||
sizes[3].set(0, 0);
|
||||
codec_yuv(r, "images/color_wheel.jpg", sizes);
|
||||
|
||||
// H2V2
|
||||
|
@ -60,7 +60,9 @@ void DDLPromiseImageHelper::uploadAllToGPU(GrContext* context) {
|
||||
|
||||
// DDL TODO: how can we tell if we need mipmapping!
|
||||
if (info.isYUV()) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
int numPixmaps;
|
||||
SkAssertResult(SkYUVAIndex::AreValidIndices(info.yuvaIndices(), &numPixmaps));
|
||||
for (int j = 0; j < numPixmaps; ++j) {
|
||||
const SkPixmap& yuvPixmap = info.yuvPixmap(j);
|
||||
|
||||
sk_sp<PromiseImageCallbackContext> callbackContext(
|
||||
@ -140,29 +142,31 @@ sk_sp<SkImage> DDLPromiseImageHelper::PromiseImageCreator(const void* rawData,
|
||||
|
||||
sk_sp<SkImage> image;
|
||||
if (curImage.isYUV()) {
|
||||
GrBackendFormat backendFormats[4];
|
||||
void* contexts[4] = { nullptr, nullptr, nullptr, nullptr };
|
||||
SkISize sizes[4];
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
GrBackendFormat backendFormats[SkYUVSizeInfo::kMaxCount];
|
||||
void* contexts[SkYUVSizeInfo::kMaxCount] = { nullptr, nullptr, nullptr, nullptr };
|
||||
SkYUVSizeInfo sizeInfo;
|
||||
// TODO: store this value somewhere?
|
||||
int textureCount;
|
||||
SkAssertResult(SkYUVAIndex::AreValidIndices(curImage.yuvaIndices(), &textureCount));
|
||||
for (int i = 0; i < textureCount; ++i) {
|
||||
const GrBackendTexture& backendTex = curImage.backendTexture(i);
|
||||
backendFormats[i] = caps->createFormatFromBackendTexture(backendTex);
|
||||
|
||||
contexts[i] = curImage.refCallbackContext(i).release();
|
||||
sizes[i].set(curImage.yuvPixmap(i).width(), curImage.yuvPixmap(i).height());
|
||||
sizeInfo.fSizes[i].set(curImage.yuvPixmap(i).width(), curImage.yuvPixmap(i).height());
|
||||
sizeInfo.fColorTypes[i] = curImage.yuvPixmap(i).colorType();
|
||||
sizeInfo.fWidthBytes[i] = curImage.yuvPixmap(i).rowBytes();
|
||||
}
|
||||
for (int i = textureCount; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
sizeInfo.fSizes[i] = SkISize::MakeEmpty();
|
||||
sizeInfo.fColorTypes[i] = kUnknown_SkColorType;
|
||||
sizeInfo.fWidthBytes[i] = 0;
|
||||
}
|
||||
|
||||
SkYUVAIndex yuvaIndices[4] = {
|
||||
SkYUVAIndex{0, SkColorChannel::kA},
|
||||
SkYUVAIndex{1, SkColorChannel::kA},
|
||||
SkYUVAIndex{2, SkColorChannel::kA},
|
||||
SkYUVAIndex{-1, SkColorChannel::kA} // TODO: enable this
|
||||
};
|
||||
|
||||
image = recorder->makeYUVAPromiseTexture(curImage.yuvColorSpace(),
|
||||
backendFormats,
|
||||
sizes,
|
||||
yuvaIndices,
|
||||
sizeInfo,
|
||||
curImage.yuvaIndices(),
|
||||
curImage.overallWidth(),
|
||||
curImage.overallHeight(),
|
||||
GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
|
||||
@ -219,17 +223,27 @@ int DDLPromiseImageHelper::addImage(SkImage* image) {
|
||||
image->uniqueID(),
|
||||
overallII);
|
||||
|
||||
SkYUVSizeInfo yuvSizeInfo;
|
||||
SkYUVSizeInfo yuvaSizeInfo;
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount];
|
||||
SkYUVColorSpace yuvColorSpace;
|
||||
const void* planes[3];
|
||||
sk_sp<SkCachedData> yuvData = ib->getPlanes(&yuvSizeInfo, &yuvColorSpace, planes);
|
||||
const void* planes[SkYUVSizeInfo::kMaxCount];
|
||||
sk_sp<SkCachedData> yuvData = ib->getPlanes(&yuvaSizeInfo, yuvaIndices, &yuvColorSpace, planes);
|
||||
if (yuvData) {
|
||||
newImageInfo.setYUVData(std::move(yuvData), yuvColorSpace);
|
||||
newImageInfo.setYUVData(std::move(yuvData), yuvaIndices, yuvColorSpace);
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
SkImageInfo planeII = SkImageInfo::MakeA8(yuvSizeInfo.fSizes[i].fWidth,
|
||||
yuvSizeInfo.fSizes[i].fHeight);
|
||||
newImageInfo.addYUVPlane(i, planeII, planes[i], yuvSizeInfo.fWidthBytes[i]);
|
||||
for (int i = 0; i < SkYUVSizeInfo::kMaxCount; ++i) {
|
||||
if (kUnknown_SkColorType == yuvaSizeInfo.fColorTypes[i]) {
|
||||
SkASSERT(!yuvaSizeInfo.fSizes[i].fWidth &&
|
||||
!yuvaSizeInfo.fSizes[i].fHeight &&
|
||||
!yuvaSizeInfo.fWidthBytes[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
SkImageInfo planeII = SkImageInfo::Make(yuvaSizeInfo.fSizes[i].fWidth,
|
||||
yuvaSizeInfo.fSizes[i].fHeight,
|
||||
yuvaSizeInfo.fColorTypes[i],
|
||||
kUnpremul_SkAlphaType);
|
||||
newImageInfo.addYUVPlane(i, planeII, planes[i], yuvaSizeInfo.fWidthBytes[i]);
|
||||
}
|
||||
} else {
|
||||
sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
|
||||
|
@ -13,12 +13,14 @@
|
||||
|
||||
#include "GrBackendSurface.h"
|
||||
#include "SkCachedData.h"
|
||||
#include "SkYUVAIndex.h"
|
||||
#include "SkYUVSizeInfo.h"
|
||||
|
||||
class GrContext;
|
||||
class SkDeferredDisplayListRecorder;
|
||||
class SkImage;
|
||||
class SkPicture;
|
||||
struct SkYUVAIndex;
|
||||
|
||||
// This class consolidates tracking & extraction of the original image data from an skp,
|
||||
// the upload of said data to the GPU and the fulfillment of promise images.
|
||||
@ -116,9 +118,13 @@ private:
|
||||
SkASSERT(this->isYUV());
|
||||
return fYUVColorSpace;
|
||||
}
|
||||
const SkYUVAIndex* yuvaIndices() const {
|
||||
SkASSERT(this->isYUV());
|
||||
return fYUVAIndices;
|
||||
}
|
||||
const SkPixmap& yuvPixmap(int index) const {
|
||||
SkASSERT(this->isYUV());
|
||||
SkASSERT(index >= 0 && index < 3);
|
||||
SkASSERT(index >= 0 && index < SkYUVSizeInfo::kMaxCount);
|
||||
return fYUVPlanes[index];
|
||||
}
|
||||
const SkBitmap& normalBitmap() const {
|
||||
@ -127,34 +133,37 @@ private:
|
||||
}
|
||||
|
||||
void setCallbackContext(int index, sk_sp<PromiseImageCallbackContext> callbackContext) {
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? 3 : 1));
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVSizeInfo::kMaxCount : 1));
|
||||
fCallbackContexts[index] = callbackContext;
|
||||
}
|
||||
PromiseImageCallbackContext* callbackContext(int index) {
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? 3 : 1));
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVSizeInfo::kMaxCount : 1));
|
||||
return fCallbackContexts[index].get();
|
||||
}
|
||||
sk_sp<PromiseImageCallbackContext> refCallbackContext(int index) const {
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? 3 : 1));
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVSizeInfo::kMaxCount : 1));
|
||||
return fCallbackContexts[index];
|
||||
}
|
||||
|
||||
const GrCaps* caps() const { return fCallbackContexts[0]->caps(); }
|
||||
|
||||
const GrBackendTexture& backendTexture(int index) const {
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? 3 : 1));
|
||||
SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVSizeInfo::kMaxCount : 1));
|
||||
return fCallbackContexts[index]->backendTexture();
|
||||
}
|
||||
|
||||
void setNormalBitmap(const SkBitmap& bm) { fBitmap = bm; }
|
||||
|
||||
void setYUVData(sk_sp<SkCachedData> yuvData, SkYUVColorSpace cs) {
|
||||
void setYUVData(sk_sp<SkCachedData> yuvData,
|
||||
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
|
||||
SkYUVColorSpace cs) {
|
||||
fYUVData = yuvData;
|
||||
memcpy(fYUVAIndices, yuvaIndices, sizeof(fYUVAIndices));
|
||||
fYUVColorSpace = cs;
|
||||
}
|
||||
void addYUVPlane(int index, const SkImageInfo& ii, const void* plane, size_t widthBytes) {
|
||||
SkASSERT(this->isYUV());
|
||||
SkASSERT(index >= 0 && index < 3);
|
||||
SkASSERT(index >= 0 && index < SkYUVSizeInfo::kMaxCount);
|
||||
fYUVPlanes[index].reset(ii, plane, widthBytes);
|
||||
}
|
||||
|
||||
@ -170,10 +179,11 @@ private:
|
||||
// CPU-side cache of a YUV SkImage's contents
|
||||
sk_sp<SkCachedData> fYUVData; // when !null, this is a YUV image
|
||||
SkYUVColorSpace fYUVColorSpace = kJPEG_SkYUVColorSpace;
|
||||
SkPixmap fYUVPlanes[3];
|
||||
SkYUVAIndex fYUVAIndices[SkYUVAIndex::kIndexCount];
|
||||
SkPixmap fYUVPlanes[SkYUVSizeInfo::kMaxCount];
|
||||
|
||||
// Up to 3 for a YUV image. Only one for a normal image.
|
||||
sk_sp<PromiseImageCallbackContext> fCallbackContexts[3];
|
||||
// Up to SkYUVSizeInfo::kMaxCount for a YUVA image. Only one for a normal image.
|
||||
sk_sp<PromiseImageCallbackContext> fCallbackContexts[SkYUVSizeInfo::kMaxCount];
|
||||
};
|
||||
|
||||
// This stack-based context allows each thread to re-inflate the image indices into
|
||||
|
Loading…
Reference in New Issue
Block a user