Revert "Push SkYUVAInfo into GrYUVToRGBEffect."
This reverts commit b60255033d
.
Reason for revert: GM needs fix for abandoned context
Original change's description:
> Push SkYUVAInfo into GrYUVToRGBEffect.
>
> Wrap up SkYUVAInfo and proxies into new type GrYUVATextureProxies.
>
> Bug: skia:10632
> Change-Id: Ic907d78a1a40af3c8ef838021749839c422d62dc
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/353042
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Jim Van Verth <jvanverth@google.com>
TBR=jvanverth@google.com,bsalomon@google.com
Change-Id: Ia5a1121ed388ad04ef86121a3f7905772316a200
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:10632
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/353618
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Auto-Submit: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
a65441b3c4
commit
0e4a29af9d
@ -16,15 +16,14 @@
|
|||||||
#include "include/core/SkScalar.h"
|
#include "include/core/SkScalar.h"
|
||||||
#include "include/core/SkSize.h"
|
#include "include/core/SkSize.h"
|
||||||
#include "include/core/SkString.h"
|
#include "include/core/SkString.h"
|
||||||
#include "include/core/SkYUVAInfo.h"
|
#include "include/private/GrTypesPriv.h"
|
||||||
#include "include/core/SkYUVAPixmaps.h"
|
#include "src/core/SkYUVAInfoLocation.h"
|
||||||
#include "src/gpu/GrBitmapTextureMaker.h"
|
#include "src/gpu/GrBitmapTextureMaker.h"
|
||||||
#include "src/gpu/GrDirectContextPriv.h"
|
#include "src/gpu/GrDirectContextPriv.h"
|
||||||
#include "src/gpu/GrPaint.h"
|
#include "src/gpu/GrPaint.h"
|
||||||
#include "src/gpu/GrSamplerState.h"
|
#include "src/gpu/GrSamplerState.h"
|
||||||
#include "src/gpu/GrSurfaceDrawContext.h"
|
#include "src/gpu/GrSurfaceDrawContext.h"
|
||||||
#include "src/gpu/GrTextureProxy.h"
|
#include "src/gpu/GrTextureProxy.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -32,6 +31,10 @@
|
|||||||
|
|
||||||
class SkCanvas;
|
class SkCanvas;
|
||||||
|
|
||||||
|
#define YSIZE 8
|
||||||
|
#define USIZE 4
|
||||||
|
#define VSIZE 4
|
||||||
|
|
||||||
namespace skiagm {
|
namespace skiagm {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -52,16 +55,13 @@ protected:
|
|||||||
|
|
||||||
SkISize onISize() override { return {1310, 540}; }
|
SkISize onISize() override { return {1310, 540}; }
|
||||||
|
|
||||||
void makePixmaps() {
|
void onOnceBeforeDraw() override {
|
||||||
SkYUVAInfo yuvaInfo = SkYUVAInfo({8, 8},
|
SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
|
||||||
SkYUVAInfo::PlaneConfig::kY_U_V,
|
fBitmaps[0].allocPixels(yinfo);
|
||||||
SkYUVAInfo::Subsampling::k420,
|
SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
|
||||||
kJPEG_Full_SkYUVColorSpace);
|
fBitmaps[1].allocPixels(uinfo);
|
||||||
SkColorType colorTypes[] = {kAlpha_8_SkColorType,
|
SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
|
||||||
kAlpha_8_SkColorType,
|
fBitmaps[2].allocPixels(vinfo);
|
||||||
kAlpha_8_SkColorType};
|
|
||||||
SkYUVAPixmapInfo pmapInfo(yuvaInfo, colorTypes, nullptr);
|
|
||||||
fPixmaps = SkYUVAPixmaps::Allocate(pmapInfo);
|
|
||||||
|
|
||||||
unsigned char innerY[16] = {149, 160, 130, 105,
|
unsigned char innerY[16] = {149, 160, 130, 105,
|
||||||
160, 130, 105, 149,
|
160, 130, 105, 149,
|
||||||
@ -70,62 +70,45 @@ protected:
|
|||||||
unsigned char innerU[4] = {43, 75, 145, 200};
|
unsigned char innerU[4] = {43, 75, 145, 200};
|
||||||
unsigned char innerV[4] = {88, 180, 200, 43};
|
unsigned char innerV[4] = {88, 180, 200, 43};
|
||||||
int outerYUV[] = {128, 128, 128};
|
int outerYUV[] = {128, 128, 128};
|
||||||
SkBitmap bitmaps[3];
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
bitmaps[i].installPixels(fPixmaps.plane(i));
|
fBitmaps[i].eraseColor(SkColorSetARGB(outerYUV[i], 0, 0, 0));
|
||||||
bitmaps[i].eraseColor(SkColorSetARGB(outerYUV[i], 0, 0, 0));
|
|
||||||
}
|
}
|
||||||
SkPixmap innerYPM(SkImageInfo::MakeA8(4, 4), innerY, 4);
|
SkPixmap innerYPM(SkImageInfo::MakeA8(4, 4), innerY, 4);
|
||||||
SkPixmap innerUPM(SkImageInfo::MakeA8(2, 2), innerU, 2);
|
SkPixmap innerUPM(SkImageInfo::MakeA8(2, 2), innerU, 2);
|
||||||
SkPixmap innerVPM(SkImageInfo::MakeA8(2, 2), innerV, 2);
|
SkPixmap innerVPM(SkImageInfo::MakeA8(2, 2), innerV, 2);
|
||||||
bitmaps[0].writePixels(innerYPM, 2, 2);
|
fBitmaps[0].writePixels(innerYPM, 2, 2);
|
||||||
bitmaps[1].writePixels(innerUPM, 1, 1);
|
fBitmaps[1].writePixels(innerUPM, 1, 1);
|
||||||
bitmaps[2].writePixels(innerVPM, 1, 1);
|
fBitmaps[2].writePixels(innerVPM, 1, 1);
|
||||||
|
for (auto& fBitmap : fBitmaps) {
|
||||||
|
fBitmap.setImmutable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawResult onGpuSetup(GrDirectContext* context, SkString* errorMsg) override {
|
DrawResult onDraw(GrRecordingContext* context, GrSurfaceDrawContext* surfaceDrawContext,
|
||||||
if (!context) {
|
SkCanvas* canvas, SkString* errorMsg) override {
|
||||||
return DrawResult::kSkip;
|
GrSurfaceProxyView views[3];
|
||||||
}
|
|
||||||
if (!fPixmaps.isValid()) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
this->makePixmaps();
|
GrBitmapTextureMaker maker(context, fBitmaps[i], GrImageTexGenPolicy::kDraw);
|
||||||
}
|
|
||||||
GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
|
|
||||||
GrColorType colorTypes[SkYUVAInfo::kMaxPlanes];
|
|
||||||
for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
|
|
||||||
SkBitmap bitmap;
|
|
||||||
bitmap.installPixels(fPixmaps.plane(i));
|
|
||||||
bitmap.setImmutable();
|
|
||||||
GrBitmapTextureMaker maker(
|
|
||||||
context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
|
|
||||||
views[i] = maker.view(GrMipmapped::kNo);
|
views[i] = maker.view(GrMipmapped::kNo);
|
||||||
if (!views[i]) {
|
if (!views[i]) {
|
||||||
*errorMsg = "Failed to create proxy";
|
*errorMsg = "Failed to create proxy";
|
||||||
return DrawResult::kFail;
|
return DrawResult::kFail;
|
||||||
}
|
}
|
||||||
colorTypes[i] = SkColorTypeToGrColorType(bitmap.colorType());
|
|
||||||
}
|
}
|
||||||
fProxies = GrYUVATextureProxies(fPixmaps.yuvaInfo(), views, colorTypes);
|
|
||||||
if (!fProxies.isValid()) {
|
|
||||||
*errorMsg = "Failed to create GrYUVATextureProxies";
|
|
||||||
return DrawResult::kFail;
|
|
||||||
}
|
|
||||||
return DrawResult::kOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onGpuTeardown() override { fProxies = {}; }
|
|
||||||
|
|
||||||
DrawResult onDraw(GrRecordingContext* context,
|
|
||||||
GrSurfaceDrawContext* surfaceDrawContext,
|
|
||||||
SkCanvas* canvas,
|
|
||||||
SkString* errorMsg) override {
|
|
||||||
static const GrSamplerState::Filter kFilters[] = {GrSamplerState::Filter::kNearest,
|
static const GrSamplerState::Filter kFilters[] = {GrSamplerState::Filter::kNearest,
|
||||||
GrSamplerState::Filter::kLinear};
|
GrSamplerState::Filter::kLinear};
|
||||||
static const SkRect kColorRect = SkRect::MakeLTRB(2.f, 2.f, 6.f, 6.f);
|
static const SkRect kColorRect = SkRect::MakeLTRB(2.f, 2.f, 6.f, 6.f);
|
||||||
|
|
||||||
|
SkYUVAInfo::YUVALocations yuvaLocations = {{
|
||||||
|
{ 0, SkColorChannel::kA},
|
||||||
|
{ 1, SkColorChannel::kA},
|
||||||
|
{ 2, SkColorChannel::kA},
|
||||||
|
{-1, SkColorChannel::kA}
|
||||||
|
}};
|
||||||
// Outset to visualize wrap modes.
|
// Outset to visualize wrap modes.
|
||||||
SkRect rect = SkRect::Make(fProxies.yuvaInfo().dimensions());
|
SkRect rect = SkRect::MakeWH(YSIZE, YSIZE).makeOutset(YSIZE/2, YSIZE/2);
|
||||||
rect = rect.makeOutset(fProxies.yuvaInfo().width()/2.f, fProxies.yuvaInfo().height()/2.f);
|
|
||||||
|
|
||||||
SkScalar y = kTestPad;
|
SkScalar y = kTestPad;
|
||||||
// Rows are filter modes.
|
// Rows are filter modes.
|
||||||
@ -146,8 +129,9 @@ protected:
|
|||||||
samplerState.setWrapModeY(wm);
|
samplerState.setWrapModeY(wm);
|
||||||
}
|
}
|
||||||
const auto& caps = *context->priv().caps();
|
const auto& caps = *context->priv().caps();
|
||||||
std::unique_ptr<GrFragmentProcessor> fp =
|
std::unique_ptr<GrFragmentProcessor> fp(
|
||||||
GrYUVtoRGBEffect::Make(fProxies, samplerState, caps, SkMatrix::I(), subset);
|
GrYUVtoRGBEffect::Make(views, yuvaLocations, kJPEG_SkYUVColorSpace,
|
||||||
|
samplerState, caps, SkMatrix::I(), subset));
|
||||||
if (fp) {
|
if (fp) {
|
||||||
GrPaint grPaint;
|
GrPaint grPaint;
|
||||||
grPaint.setColorFragmentProcessor(std::move(fp));
|
grPaint.setColorFragmentProcessor(std::move(fp));
|
||||||
@ -161,11 +145,10 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return DrawResult::kOk;
|
return DrawResult::kOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkYUVAPixmaps fPixmaps;
|
SkBitmap fBitmaps[3];
|
||||||
GrYUVATextureProxies fProxies;
|
|
||||||
|
|
||||||
static constexpr SkScalar kTestPad = 10.f;
|
static constexpr SkScalar kTestPad = 10.f;
|
||||||
|
|
||||||
|
@ -277,8 +277,6 @@ skia_gpu_sources = [
|
|||||||
"$_src/gpu/GrXferProcessor.cpp",
|
"$_src/gpu/GrXferProcessor.cpp",
|
||||||
"$_src/gpu/GrXferProcessor.h",
|
"$_src/gpu/GrXferProcessor.h",
|
||||||
"$_src/gpu/GrYUVABackendTextures.cpp",
|
"$_src/gpu/GrYUVABackendTextures.cpp",
|
||||||
"$_src/gpu/GrYUVATextureProxies.cpp",
|
|
||||||
"$_src/gpu/GrYUVATextureProxies.h",
|
|
||||||
|
|
||||||
# Ops
|
# Ops
|
||||||
"$_src/gpu/effects/GrBezierEffect.cpp",
|
"$_src/gpu/effects/GrBezierEffect.cpp",
|
||||||
|
@ -93,16 +93,6 @@ public:
|
|||||||
|
|
||||||
static constexpr int kMaxPlanes = 4;
|
static constexpr int kMaxPlanes = 4;
|
||||||
|
|
||||||
/** ratio of Y/A values to U/V values in x and y. */
|
|
||||||
static std::tuple<int, int> SubsamplingFactors(Subsampling);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SubsamplingFactors(Subsampling) if planedIdx refers to a U/V plane and otherwise {1, 1} if
|
|
||||||
* inputs are valid. Invalid inputs consist of incompatible PlaneConfig/Subsampling/planeIdx
|
|
||||||
* combinations. {0, 0} is returned for invalid inputs.
|
|
||||||
*/
|
|
||||||
static std::tuple<int, int> PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given image dimensions, a planer configuration, subsampling, and origin, determine the
|
* Given image dimensions, a planer configuration, subsampling, and origin, determine the
|
||||||
* expected size of each plane. Returns the number of expected planes. planeDimensions[0]
|
* expected size of each plane. Returns the number of expected planes. planeDimensions[0]
|
||||||
@ -156,10 +146,6 @@ public:
|
|||||||
PlaneConfig planeConfig() const { return fPlaneConfig; }
|
PlaneConfig planeConfig() const { return fPlaneConfig; }
|
||||||
Subsampling subsampling() const { return fSubsampling; }
|
Subsampling subsampling() const { return fSubsampling; }
|
||||||
|
|
||||||
std::tuple<int, int> planeSubsamplingFactors(int planeIdx) const {
|
|
||||||
return PlaneSubsamplingFactors(fPlaneConfig, fSubsampling, planeIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dimensions of the full resolution image (after planes have been oriented to how the image
|
* Dimensions of the full resolution image (after planes have been oriented to how the image
|
||||||
* is displayed as indicated by fOrigin).
|
* is displayed as indicated by fOrigin).
|
||||||
@ -174,10 +160,6 @@ public:
|
|||||||
|
|
||||||
SkEncodedOrigin origin() const { return fOrigin; }
|
SkEncodedOrigin origin() const { return fOrigin; }
|
||||||
|
|
||||||
SkMatrix originMatrix() const {
|
|
||||||
return SkEncodedOriginToMatrix(fOrigin, this->width(), this->height());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
|
bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,12 +199,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const;
|
SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a SkYUVAInfo that is identical to this one but with the passed dimensions. If the
|
|
||||||
* passed dimensions is empty then the result will be an invalid SkYUVAInfo.
|
|
||||||
*/
|
|
||||||
SkYUVAInfo makeDimensions(SkISize) const;
|
|
||||||
|
|
||||||
bool operator==(const SkYUVAInfo& that) const;
|
bool operator==(const SkYUVAInfo& that) const;
|
||||||
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
|
bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
|
||||||
|
|
||||||
|
@ -24,54 +24,6 @@ static bool is_plane_config_compatible_with_subsampling(SkYUVAInfo::PlaneConfig
|
|||||||
config != SkYUVAInfo::PlaneConfig::kUYVA);
|
config != SkYUVAInfo::PlaneConfig::kUYVA);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<int, int> SkYUVAInfo::SubsamplingFactors(Subsampling subsampling) {
|
|
||||||
switch (subsampling) {
|
|
||||||
case Subsampling::kUnknown: return {0, 0};
|
|
||||||
case Subsampling::k444: return {1, 1};
|
|
||||||
case Subsampling::k422: return {2, 1};
|
|
||||||
case Subsampling::k420: return {2, 2};
|
|
||||||
case Subsampling::k440: return {1, 2};
|
|
||||||
case Subsampling::k411: return {4, 1};
|
|
||||||
case Subsampling::k410: return {4, 2};
|
|
||||||
}
|
|
||||||
SkUNREACHABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<int, int> SkYUVAInfo::PlaneSubsamplingFactors(PlaneConfig planeConfig,
|
|
||||||
Subsampling subsampling,
|
|
||||||
int planeIdx) {
|
|
||||||
if (!is_plane_config_compatible_with_subsampling(planeConfig, subsampling) ||
|
|
||||||
planeIdx < 0 ||
|
|
||||||
planeIdx > NumPlanes(planeConfig)) {
|
|
||||||
return {0, 0};
|
|
||||||
}
|
|
||||||
bool isSubsampledPlane = false;
|
|
||||||
switch (planeConfig) {
|
|
||||||
case PlaneConfig::kUnknown: SkUNREACHABLE;
|
|
||||||
|
|
||||||
case PlaneConfig::kY_U_V:
|
|
||||||
case PlaneConfig::kY_V_U:
|
|
||||||
case PlaneConfig::kY_U_V_A:
|
|
||||||
case PlaneConfig::kY_V_U_A:
|
|
||||||
isSubsampledPlane = planeIdx == 1 || planeIdx == 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaneConfig::kY_UV:
|
|
||||||
case PlaneConfig::kY_VU:
|
|
||||||
case PlaneConfig::kY_UV_A:
|
|
||||||
case PlaneConfig::kY_VU_A:
|
|
||||||
isSubsampledPlane = planeIdx == 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaneConfig::kYUV:
|
|
||||||
case PlaneConfig::kUYV:
|
|
||||||
case PlaneConfig::kYUVA:
|
|
||||||
case PlaneConfig::kUYVA:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return isSubsampledPlane ? SubsamplingFactors(subsampling) : std::make_tuple(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
|
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
|
||||||
PlaneConfig planeConfig,
|
PlaneConfig planeConfig,
|
||||||
Subsampling subsampling,
|
Subsampling subsampling,
|
||||||
@ -358,11 +310,13 @@ SkYUVAInfo::YUVALocations SkYUVAInfo::toYUVALocations(const uint32_t* channelFla
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkYUVAInfo SkYUVAInfo::makeSubsampling(SkYUVAInfo::Subsampling subsampling) const {
|
SkYUVAInfo SkYUVAInfo::makeSubsampling(SkYUVAInfo::Subsampling subsampling) const {
|
||||||
return {fDimensions, fPlaneConfig, subsampling, fYUVColorSpace, fOrigin, fSitingX, fSitingY};
|
return {fDimensions,
|
||||||
}
|
fPlaneConfig,
|
||||||
|
subsampling,
|
||||||
SkYUVAInfo SkYUVAInfo::makeDimensions(SkISize dimensions) const {
|
fYUVColorSpace,
|
||||||
return {dimensions, fPlaneConfig, fSubsampling, fYUVColorSpace, fOrigin, fSitingX, fSitingY};
|
fOrigin,
|
||||||
|
fSitingX,
|
||||||
|
fSitingY};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkYUVAInfo::operator==(const SkYUVAInfo& that) const {
|
bool SkYUVAInfo::operator==(const SkYUVAInfo& that) const {
|
||||||
|
@ -77,16 +77,12 @@ std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProc
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& caps = *fImage->context()->priv().caps();
|
const auto& caps = *fImage->context()->priv().caps();
|
||||||
auto fp = GrYUVtoRGBEffect::Make(fImage->fYUVAProxies,
|
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVALocations, fImage->fYUVColorSpace,
|
||||||
samplerState,
|
samplerState, caps, textureMatrix, subset, domain);
|
||||||
caps,
|
|
||||||
textureMatrix,
|
|
||||||
subset,
|
|
||||||
domain);
|
|
||||||
if (fImage->fFromColorSpace) {
|
if (fImage->fFromColorSpace) {
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
|
||||||
fImage->fFromColorSpace.get(), fImage->alphaType(),
|
fImage->alphaType(), fImage->colorSpace(),
|
||||||
fImage->colorSpace(), kPremul_SkAlphaType);
|
kPremul_SkAlphaType);
|
||||||
}
|
}
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
@ -100,12 +96,12 @@ std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createBicubicFragm
|
|||||||
SkImage::CubicResampler kernel) {
|
SkImage::CubicResampler kernel) {
|
||||||
const auto& caps = *fImage->context()->priv().caps();
|
const auto& caps = *fImage->context()->priv().caps();
|
||||||
GrSamplerState samplerState(wrapX, wrapY, GrSamplerState::Filter::kNearest);
|
GrSamplerState samplerState(wrapX, wrapY, GrSamplerState::Filter::kNearest);
|
||||||
auto fp = GrYUVtoRGBEffect::Make(fImage->fYUVAProxies, samplerState, caps, SkMatrix::I(),
|
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVALocations, fImage->fYUVColorSpace,
|
||||||
subset, domain);
|
samplerState, caps, SkMatrix::I(), subset, domain);
|
||||||
fp = GrBicubicEffect::Make(std::move(fp),
|
fp = GrBicubicEffect::Make(std::move(fp),
|
||||||
fImage->alphaType(),
|
fImage->alphaType(),
|
||||||
textureMatrix,
|
textureMatrix,
|
||||||
kernel,
|
kernel /*GrBicubicEffect::gMitchell*/,
|
||||||
GrBicubicEffect::Direction::kXY);
|
GrBicubicEffect::Direction::kXY);
|
||||||
if (fImage->fFromColorSpace) {
|
if (fImage->fFromColorSpace) {
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google LLC
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
static int num_channels(uint32_t channelFlags) {
|
|
||||||
switch (channelFlags) {
|
|
||||||
case kRed_SkColorChannelFlag : return 1;
|
|
||||||
case kAlpha_SkColorChannelFlag : return 1;
|
|
||||||
case kGray_SkColorChannelFlag : return 1;
|
|
||||||
case kGrayAlpha_SkColorChannelFlags : return 2;
|
|
||||||
case kRG_SkColorChannelFlags : return 2;
|
|
||||||
case kRGB_SkColorChannelFlags : return 3;
|
|
||||||
case kRGBA_SkColorChannelFlags : return 4;
|
|
||||||
|
|
||||||
default:
|
|
||||||
SkDEBUGFAILF("Unexpected channel combination 0x%08x", channelFlags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
|
|
||||||
sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes],
|
|
||||||
GrSurfaceOrigin textureOrigin)
|
|
||||||
: fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
|
|
||||||
int n = yuvaInfo.numPlanes();
|
|
||||||
if (n == 0) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t textureChannelMasks[SkYUVAInfo::kMaxPlanes];
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
if (!proxies[i]) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
textureChannelMasks[i] = proxies[i]->backendFormat().channelMask();
|
|
||||||
}
|
|
||||||
fYUVALocations = yuvaInfo.toYUVALocations(textureChannelMasks);
|
|
||||||
if (fYUVALocations[0].fPlane < 0) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fMipmapped = GrMipmapped::kYes;
|
|
||||||
for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
|
|
||||||
if (!proxies[i]) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SkASSERT(proxies[i]->asTextureProxy());
|
|
||||||
if (proxies[i]->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
|
|
||||||
fMipmapped = GrMipmapped::kNo;
|
|
||||||
}
|
|
||||||
fProxies[i] = std::move(proxies[i]);
|
|
||||||
}
|
|
||||||
SkASSERT(this->isValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
|
|
||||||
GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes],
|
|
||||||
GrColorType colorTypes[SkYUVAInfo::kMaxPlanes])
|
|
||||||
: fYUVAInfo(yuvaInfo) {
|
|
||||||
uint32_t pixmapChannelMasks[SkYUVAInfo::kMaxPlanes];
|
|
||||||
int n = yuvaInfo.numPlanes();
|
|
||||||
if (n == 0) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fMipmapped = GrMipmapped::kYes;
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
pixmapChannelMasks[i] = GrColorTypeChannelFlags(colorTypes[i]);
|
|
||||||
SkASSERT(num_channels(pixmapChannelMasks[i]) <=
|
|
||||||
num_channels(views[i].proxy()->backendFormat().channelMask()));
|
|
||||||
if (!views[i] || views[i].origin() != views[0].origin()) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (views[i].proxy()->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
|
|
||||||
fMipmapped = GrMipmapped::kNo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Initial locations refer to the CPU pixmap channels.
|
|
||||||
fYUVALocations = yuvaInfo.toYUVALocations(pixmapChannelMasks);
|
|
||||||
if (fYUVALocations[0].fPlane < 0) {
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run each location through the proxy view's swizzle to get the actual texture format channel.
|
|
||||||
for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
|
|
||||||
int plane = fYUVALocations[i].fPlane;
|
|
||||||
if (plane >= 0) {
|
|
||||||
int chanAsIdx = static_cast<int>(fYUVALocations[i].fChannel);
|
|
||||||
switch (views[plane].swizzle()[chanAsIdx]) {
|
|
||||||
case 'r': fYUVALocations[i].fChannel = SkColorChannel::kR; break;
|
|
||||||
case 'g': fYUVALocations[i].fChannel = SkColorChannel::kG; break;
|
|
||||||
case 'b': fYUVALocations[i].fChannel = SkColorChannel::kB; break;
|
|
||||||
case 'a': fYUVALocations[i].fChannel = SkColorChannel::kA; break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
SkDEBUGFAILF("Unexpected swizzle value: %c", views[i].swizzle()[chanAsIdx]);
|
|
||||||
*this = {};
|
|
||||||
SkASSERT(!this->isValid());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
fProxies[i] = views[i].detachProxy();
|
|
||||||
}
|
|
||||||
fTextureOrigin = views[0].origin();
|
|
||||||
SkASSERT(this->isValid());
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2021 Google LLC
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GrYUVATextureProxies_DEFINED
|
|
||||||
#define GrYUVATextureProxies_DEFINED
|
|
||||||
|
|
||||||
#include "include/core/SkYUVAInfo.h"
|
|
||||||
#include "src/core/SkYUVAInfoLocation.h"
|
|
||||||
#include "src/gpu/GrSurfaceProxy.h"
|
|
||||||
#include "src/gpu/GrSurfaceProxyView.h"
|
|
||||||
|
|
||||||
class GrSurfaceProxyView;
|
|
||||||
|
|
||||||
class GrYUVATextureProxies {
|
|
||||||
public:
|
|
||||||
GrYUVATextureProxies() = default;
|
|
||||||
|
|
||||||
/** Assumes all planes are sampled with a default "rgba" swizzle. */
|
|
||||||
GrYUVATextureProxies(const SkYUVAInfo&,
|
|
||||||
sk_sp<GrSurfaceProxy>[SkYUVAInfo::kMaxPlanes],
|
|
||||||
GrSurfaceOrigin textureOrigin);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When uploading pixmaps to textures it is important that we account for how the original
|
|
||||||
* pixmaps' channels are swizzled into the texture during upload. This will compute a swizzle
|
|
||||||
* for each texture based on the original color types and the views' swizzles. The views must
|
|
||||||
* all have the same origin or the result will be an invalid GrYUVATextureProxies.
|
|
||||||
*/
|
|
||||||
GrYUVATextureProxies(const SkYUVAInfo&,
|
|
||||||
GrSurfaceProxyView[SkYUVAInfo::kMaxPlanes],
|
|
||||||
GrColorType[SkYUVAInfo::kMaxPlanes]);
|
|
||||||
|
|
||||||
GrYUVATextureProxies(const GrYUVATextureProxies&) = default;
|
|
||||||
GrYUVATextureProxies(GrYUVATextureProxies&&) = default;
|
|
||||||
|
|
||||||
GrYUVATextureProxies& operator=(const GrYUVATextureProxies&) = default;
|
|
||||||
GrYUVATextureProxies& operator=(GrYUVATextureProxies&&) = default;
|
|
||||||
|
|
||||||
const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
|
|
||||||
|
|
||||||
int numPlanes() const { return fYUVAInfo.numPlanes(); }
|
|
||||||
|
|
||||||
GrSurfaceOrigin textureOrigin() const { return fTextureOrigin; }
|
|
||||||
|
|
||||||
// Overall set of YUVA proxies is mip mapped if each plane is mip mapped.
|
|
||||||
GrMipmapped mipmapped() const { return fMipmapped; }
|
|
||||||
|
|
||||||
GrSurfaceProxy* proxy(int i) const { return fProxies[i].get(); }
|
|
||||||
|
|
||||||
const std::array<sk_sp<GrSurfaceProxy>, SkYUVAInfo::kMaxPlanes>& proxies() const {
|
|
||||||
return fProxies;
|
|
||||||
}
|
|
||||||
|
|
||||||
sk_sp<GrSurfaceProxy> refProxy(int i) const { return fProxies[i]; }
|
|
||||||
|
|
||||||
GrSurfaceProxyView makeView(int i) const {
|
|
||||||
return {fProxies[i], fTextureOrigin, GrSwizzle::RGBA()};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValid() const { return fYUVAInfo.isValid(); }
|
|
||||||
|
|
||||||
const SkYUVAInfo::YUVALocations& yuvaLocations() const { return fYUVALocations; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::array<sk_sp<GrSurfaceProxy>, SkYUVAInfo::kMaxPlanes> fProxies;
|
|
||||||
SkYUVAInfo fYUVAInfo;
|
|
||||||
GrSurfaceOrigin fTextureOrigin = kTopLeft_GrSurfaceOrigin;
|
|
||||||
GrMipmapped fMipmapped = GrMipmapped::kNo;
|
|
||||||
SkYUVAInfo::YUVALocations fYUVALocations = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -7,10 +7,8 @@
|
|||||||
|
|
||||||
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
||||||
|
|
||||||
#include "include/core/SkYUVAInfo.h"
|
|
||||||
#include "src/core/SkYUVMath.h"
|
#include "src/core/SkYUVMath.h"
|
||||||
#include "src/gpu/GrTexture.h"
|
#include "src/gpu/GrTexture.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/gpu/effects/GrMatrixEffect.h"
|
#include "src/gpu/effects/GrMatrixEffect.h"
|
||||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||||
@ -18,82 +16,88 @@
|
|||||||
#include "src/sksl/SkSLCPP.h"
|
#include "src/sksl/SkSLCPP.h"
|
||||||
#include "src/sksl/SkSLUtil.h"
|
#include "src/sksl/SkSLUtil.h"
|
||||||
|
|
||||||
static void border_colors(const GrYUVATextureProxies& yuvaProxies, float planeBorders[4][4]) {
|
static void border_colors(SkYUVColorSpace cs,
|
||||||
|
const SkYUVAInfo::YUVALocations& locations,
|
||||||
|
float planeBorders[4][4]) {
|
||||||
float m[20];
|
float m[20];
|
||||||
SkColorMatrix_RGB2YUV(yuvaProxies.yuvaInfo().yuvColorSpace(), m);
|
SkColorMatrix_RGB2YUV(cs, m);
|
||||||
for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
|
int i = 0;
|
||||||
auto [plane, channel] = yuvaProxies.yuvaLocations()[i];
|
for (auto [plane, channel] : locations) {
|
||||||
if (plane == -1) {
|
if (plane == -1) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
auto c = static_cast<int>(channel);
|
auto c = static_cast<int>(channel);
|
||||||
planeBorders[plane][c] = m[i*5 + 4];
|
planeBorders[plane][c] = m[i*5 + 4];
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(const GrYUVATextureProxies& yuvaProxies,
|
std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(
|
||||||
GrSamplerState samplerState,
|
GrSurfaceProxyView views[],
|
||||||
const GrCaps& caps,
|
const SkYUVAInfo::YUVALocations& locations,
|
||||||
const SkMatrix& localMatrix,
|
SkYUVColorSpace yuvColorSpace,
|
||||||
const SkRect* subset,
|
GrSamplerState samplerState,
|
||||||
const SkRect* domain) {
|
const GrCaps& caps,
|
||||||
int numPlanes = yuvaProxies.yuvaInfo().numPlanes();
|
const SkMatrix& localMatrix,
|
||||||
if (!yuvaProxies.isValid()) {
|
const SkRect* subset,
|
||||||
return nullptr;
|
const SkRect* domain) {
|
||||||
}
|
int numPlanes;
|
||||||
|
SkAssertResult(SkYUVAInfo::YUVALocation::AreValidLocations(locations, &numPlanes));
|
||||||
|
|
||||||
|
const SkISize yDimensions =
|
||||||
|
views[locations[SkYUVAInfo::YUVAChannels::kY].fPlane].proxy()->dimensions();
|
||||||
|
|
||||||
bool usesBorder = samplerState.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
|
bool usesBorder = samplerState.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
|
||||||
samplerState.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder;
|
samplerState.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder;
|
||||||
float planeBorders[4][4] = {};
|
float planeBorders[4][4] = {};
|
||||||
if (usesBorder) {
|
if (usesBorder) {
|
||||||
border_colors(yuvaProxies, planeBorders);
|
border_colors(yuvColorSpace, locations, planeBorders);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool snap[2] = {false, false};
|
bool snap[2] = {false, false};
|
||||||
std::unique_ptr<GrFragmentProcessor> planeFPs[SkYUVAInfo::kMaxPlanes];
|
std::unique_ptr<GrFragmentProcessor> planeFPs[4];
|
||||||
for (int i = 0; i < numPlanes; ++i) {
|
for (int i = 0; i < numPlanes; ++i) {
|
||||||
GrSurfaceProxyView view = yuvaProxies.makeView(i);
|
SkISize dimensions = views[i].proxy()->dimensions();
|
||||||
SkMatrix planeMatrix = yuvaProxies.yuvaInfo().originMatrix();
|
SkTCopyOnFirstWrite<SkMatrix> planeMatrix(&SkMatrix::I());
|
||||||
// The returned matrix is a view matrix but we need a local matrix.
|
|
||||||
SkAssertResult(planeMatrix.invert(&planeMatrix));
|
|
||||||
SkRect planeSubset;
|
SkRect planeSubset;
|
||||||
SkRect planeDomain;
|
SkRect planeDomain;
|
||||||
bool makeLinearWithSnap = false;
|
bool makeLinearWithSnap = false;
|
||||||
auto [ssx, ssy] = yuvaProxies.yuvaInfo().planeSubsamplingFactors(i);
|
float sx = 1.f,
|
||||||
SkASSERT(ssx > 0 && ssx <= 4);
|
sy = 1.f;
|
||||||
SkASSERT(ssy > 0 && ssy <= 2);
|
if (dimensions != yDimensions) {
|
||||||
float scaleX = 1.f;
|
|
||||||
float scaleY = 1.f;
|
|
||||||
if (ssx > 1 || ssy > 1) {
|
|
||||||
// JPEG chroma subsampling of odd dimensions produces U and V planes with the ceiling of
|
// JPEG chroma subsampling of odd dimensions produces U and V planes with the ceiling of
|
||||||
// the image size divided by the subsampling factor (2). Our API for creating YUVA
|
// the image size divided by the subsampling factor (2). Our API for creating YUVA
|
||||||
// doesn't capture the intended subsampling (and we should fix that). This fixes up 2x
|
// doesn't capture the intended subsampling (and we should fix that). This fixes up 2x
|
||||||
// subsampling for images with odd widths/heights (e.g. JPEG 420 or 422).
|
// subsampling for images with odd widths/heights (e.g. JPEG 420 or 422).
|
||||||
scaleX = 1.f/ssx;
|
sx = (float)dimensions.width() / yDimensions.width();
|
||||||
scaleY = 1.f/ssy;
|
sy = (float)dimensions.height() / yDimensions.height();
|
||||||
// We would want to add a translation to this matrix to handle other sitings.
|
if ((yDimensions.width() & 0b1) && dimensions.width() == yDimensions.width() / 2 + 1) {
|
||||||
SkASSERT(yuvaProxies.yuvaInfo().sitingX() == SkYUVAInfo::Siting::kCentered);
|
sx = 0.5f;
|
||||||
SkASSERT(yuvaProxies.yuvaInfo().sitingY() == SkYUVAInfo::Siting::kCentered);
|
}
|
||||||
planeMatrix.postConcat(SkMatrix::Scale(scaleX, scaleY));
|
if ((yDimensions.height() & 0b1) &&
|
||||||
|
dimensions.height() == yDimensions.height() / 2 + 1) {
|
||||||
|
sy = 0.5f;
|
||||||
|
}
|
||||||
|
*planeMatrix.writable() = SkMatrix::Scale(sx, sy);
|
||||||
if (subset) {
|
if (subset) {
|
||||||
planeSubset = {subset->fLeft *scaleX,
|
planeSubset = {subset->fLeft * sx,
|
||||||
subset->fTop *scaleY,
|
subset->fTop * sy,
|
||||||
subset->fRight *scaleX,
|
subset->fRight * sx,
|
||||||
subset->fBottom*scaleY};
|
subset->fBottom * sy};
|
||||||
}
|
}
|
||||||
if (domain) {
|
if (domain) {
|
||||||
planeDomain = {domain->fLeft *scaleX,
|
planeDomain = {domain->fLeft * sx,
|
||||||
domain->fTop *scaleY,
|
domain->fTop * sy,
|
||||||
domain->fRight *scaleX,
|
domain->fRight * sx,
|
||||||
domain->fBottom*scaleY};
|
domain->fBottom * sy};
|
||||||
}
|
}
|
||||||
// This promotion of nearest to linear filtering for UV planes exists to mimic
|
// This promotion of nearest to linear filtering for UV planes exists to mimic
|
||||||
// libjpeg[-turbo]'s do_fancy_upsampling option. We will filter the subsampled plane,
|
// libjpeg[-turbo]'s do_fancy_upsampling option. We will filter the subsampled plane,
|
||||||
// however we want to filter at a fixed point for each logical image pixel to simulate
|
// however we want to filter at a fixed point for each logical image pixel to simulate
|
||||||
// nearest neighbor.
|
// nearest neighbor.
|
||||||
if (samplerState.filter() == GrSamplerState::Filter::kNearest) {
|
if (samplerState.filter() == GrSamplerState::Filter::kNearest) {
|
||||||
bool snapX = (ssx != 1),
|
bool snapX = (sx != 1.f),
|
||||||
snapY = (ssy != 1);
|
snapY = (sy != 1.f);
|
||||||
makeLinearWithSnap = snapX || snapY;
|
makeLinearWithSnap = snapX || snapY;
|
||||||
snap[0] |= snapX;
|
snap[0] |= snapX;
|
||||||
snap[1] |= snapY;
|
snap[1] |= snapY;
|
||||||
@ -127,53 +131,30 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(const GrYUVATextureP
|
|||||||
// planeSubset but allows linear filtering to read pixels from the plane that are
|
// planeSubset but allows linear filtering to read pixels from the plane that are
|
||||||
// just outside planeSubset.
|
// just outside planeSubset.
|
||||||
SkRect* domainRect = domain ? &planeDomain : nullptr;
|
SkRect* domainRect = domain ? &planeDomain : nullptr;
|
||||||
planeFPs[i] = GrTextureEffect::MakeCustomLinearFilterInset(std::move(view),
|
planeFPs[i] = GrTextureEffect::MakeCustomLinearFilterInset(
|
||||||
kUnknown_SkAlphaType,
|
views[i], kUnknown_SkAlphaType, *planeMatrix, samplerState.wrapModeX(),
|
||||||
planeMatrix,
|
samplerState.wrapModeY(), planeSubset, domainRect, {sx / 2.f, sy / 2.f},
|
||||||
samplerState.wrapModeX(),
|
caps, planeBorders[i]);
|
||||||
samplerState.wrapModeY(),
|
|
||||||
planeSubset,
|
|
||||||
domainRect,
|
|
||||||
{scaleX/2.f, scaleY/2.f},
|
|
||||||
caps,
|
|
||||||
planeBorders[i]);
|
|
||||||
} else if (domain) {
|
} else if (domain) {
|
||||||
planeFPs[i] = GrTextureEffect::MakeSubset(std::move(view),
|
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||||
kUnknown_SkAlphaType,
|
*planeMatrix, samplerState, planeSubset,
|
||||||
planeMatrix,
|
planeDomain, caps, planeBorders[i]);
|
||||||
samplerState,
|
|
||||||
planeSubset,
|
|
||||||
planeDomain,
|
|
||||||
caps,
|
|
||||||
planeBorders[i]);
|
|
||||||
} else {
|
} else {
|
||||||
planeFPs[i] = GrTextureEffect::MakeSubset(std::move(view),
|
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||||
kUnknown_SkAlphaType,
|
*planeMatrix, samplerState, planeSubset,
|
||||||
planeMatrix,
|
caps, planeBorders[i]);
|
||||||
samplerState,
|
|
||||||
planeSubset,
|
|
||||||
caps,
|
|
||||||
planeBorders[i]);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GrSamplerState planeSampler = samplerState;
|
GrSamplerState planeSampler = samplerState;
|
||||||
if (makeLinearWithSnap) {
|
if (makeLinearWithSnap) {
|
||||||
planeSampler.setFilterMode(GrSamplerState::Filter::kLinear);
|
planeSampler.setFilterMode(GrSamplerState::Filter::kLinear);
|
||||||
}
|
}
|
||||||
planeFPs[i] = GrTextureEffect::Make(std::move(view),
|
planeFPs[i] = GrTextureEffect::Make(views[i], kUnknown_SkAlphaType, *planeMatrix,
|
||||||
kUnknown_SkAlphaType,
|
planeSampler, caps, planeBorders[i]);
|
||||||
planeMatrix,
|
|
||||||
planeSampler,
|
|
||||||
caps,
|
|
||||||
planeBorders[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::unique_ptr<GrFragmentProcessor> fp(
|
auto fp = std::unique_ptr<GrFragmentProcessor>(
|
||||||
new GrYUVtoRGBEffect(planeFPs,
|
new GrYUVtoRGBEffect(planeFPs, numPlanes, locations, snap, yuvColorSpace));
|
||||||
numPlanes,
|
|
||||||
yuvaProxies.yuvaLocations(),
|
|
||||||
snap,
|
|
||||||
yuvaProxies.yuvaInfo().yuvColorSpace()));
|
|
||||||
return GrMatrixEffect::Make(localMatrix, std::move(fp));
|
return GrMatrixEffect::Make(localMatrix, std::move(fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
#include "src/core/SkYUVAInfoLocation.h"
|
#include "src/core/SkYUVAInfoLocation.h"
|
||||||
#include "src/gpu/GrFragmentProcessor.h"
|
#include "src/gpu/GrFragmentProcessor.h"
|
||||||
|
|
||||||
class GrYUVATextureProxies;
|
|
||||||
|
|
||||||
class GrYUVtoRGBEffect : public GrFragmentProcessor {
|
class GrYUVtoRGBEffect : public GrFragmentProcessor {
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<GrFragmentProcessor> Make(const GrYUVATextureProxies& yuvaProxies,
|
static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView views[],
|
||||||
|
const SkYUVAInfo::YUVALocations&,
|
||||||
|
SkYUVColorSpace yuvColorSpace,
|
||||||
GrSamplerState samplerState,
|
GrSamplerState samplerState,
|
||||||
const GrCaps&,
|
const GrCaps&,
|
||||||
const SkMatrix& localMatrix = SkMatrix::I(),
|
const SkMatrix& localMatrix = SkMatrix::I(),
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include "src/gpu/GrTextureAdjuster.h"
|
#include "src/gpu/GrTextureAdjuster.h"
|
||||||
#include "src/gpu/GrTextureProxy.h"
|
#include "src/gpu/GrTextureProxy.h"
|
||||||
#include "src/gpu/GrTextureProxyPriv.h"
|
#include "src/gpu/GrTextureProxyPriv.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/gpu/SkGr.h"
|
#include "src/gpu/SkGr.h"
|
||||||
#include "src/gpu/gl/GrGLTexture.h"
|
#include "src/gpu/gl/GrGLTexture.h"
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "include/gpu/GrBackendSurface.h"
|
#include "include/gpu/GrBackendSurface.h"
|
||||||
#include "include/gpu/GrDirectContext.h"
|
#include "include/gpu/GrDirectContext.h"
|
||||||
#include "include/gpu/GrRecordingContext.h"
|
#include "include/gpu/GrRecordingContext.h"
|
||||||
#include "include/gpu/GrYUVABackendTextures.h"
|
|
||||||
#include "src/core/SkBitmapCache.h"
|
#include "src/core/SkBitmapCache.h"
|
||||||
#include "src/core/SkTLList.h"
|
#include "src/core/SkTLList.h"
|
||||||
#include "src/gpu/GrDirectContextPriv.h"
|
#include "src/gpu/GrDirectContextPriv.h"
|
||||||
@ -23,7 +22,6 @@
|
|||||||
#include "src/gpu/GrSurfaceDrawContext.h"
|
#include "src/gpu/GrSurfaceDrawContext.h"
|
||||||
#include "src/gpu/GrTexture.h"
|
#include "src/gpu/GrTexture.h"
|
||||||
#include "src/gpu/GrTextureAdjuster.h"
|
#include "src/gpu/GrTextureAdjuster.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
||||||
#include "src/image/SkImage_Gpu.h"
|
#include "src/image/SkImage_Gpu.h"
|
||||||
#include "src/image/SkReadPixelsRec.h"
|
#include "src/image/SkReadPixelsRec.h"
|
||||||
|
@ -60,6 +60,11 @@ public:
|
|||||||
static bool ValidateCompressedBackendTexture(const GrCaps*, const GrBackendTexture& tex,
|
static bool ValidateCompressedBackendTexture(const GrCaps*, const GrBackendTexture& tex,
|
||||||
SkAlphaType);
|
SkAlphaType);
|
||||||
|
|
||||||
|
static SkAlphaType GetAlphaTypeFromYUVALocations(const SkYUVAInfo::YUVALocations locations) {
|
||||||
|
return locations[SkYUVAInfo::YUVAChannels::kA].fPlane >= 0 ? kPremul_SkAlphaType
|
||||||
|
: kOpaque_SkAlphaType;
|
||||||
|
}
|
||||||
|
|
||||||
using PromiseImageTextureContext = SkDeferredDisplayListRecorder::PromiseImageTextureContext;
|
using PromiseImageTextureContext = SkDeferredDisplayListRecorder::PromiseImageTextureContext;
|
||||||
using PromiseImageTextureFulfillProc =
|
using PromiseImageTextureFulfillProc =
|
||||||
SkDeferredDisplayListRecorder::PromiseImageTextureFulfillProc;
|
SkDeferredDisplayListRecorder::PromiseImageTextureFulfillProc;
|
||||||
|
@ -34,21 +34,33 @@
|
|||||||
static constexpr auto kAssumedColorType = kRGBA_8888_SkColorType;
|
static constexpr auto kAssumedColorType = kRGBA_8888_SkColorType;
|
||||||
|
|
||||||
SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
|
SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
|
||||||
|
SkISize size,
|
||||||
uint32_t uniqueID,
|
uint32_t uniqueID,
|
||||||
GrYUVATextureProxies proxies,
|
SkYUVColorSpace colorSpace,
|
||||||
|
GrSurfaceProxyView views[],
|
||||||
|
int numViews,
|
||||||
|
const SkYUVAInfo::YUVALocations& yuvaLocations,
|
||||||
sk_sp<SkColorSpace> imageColorSpace)
|
sk_sp<SkColorSpace> imageColorSpace)
|
||||||
: INHERITED(std::move(context),
|
: INHERITED(std::move(context),
|
||||||
proxies.yuvaInfo().dimensions(),
|
size,
|
||||||
uniqueID,
|
uniqueID,
|
||||||
kAssumedColorType,
|
kAssumedColorType,
|
||||||
// If an alpha channel is present we always use kPremul. This is because,
|
// If an alpha channel is present we always switch to kPremul. This is because,
|
||||||
// although the planar data is always un-premul, the final interleaved RGB image
|
// although the planar data is always un-premul, the final interleaved RGB image
|
||||||
// is/would-be premul.
|
// is/would-be premul.
|
||||||
proxies.yuvaInfo().hasAlpha() ? kPremul_SkAlphaType : kOpaque_SkAlphaType,
|
GetAlphaTypeFromYUVALocations(yuvaLocations),
|
||||||
std::move(imageColorSpace))
|
std::move(imageColorSpace))
|
||||||
, fYUVAProxies(std::move(proxies)) {
|
, fNumViews(numViews)
|
||||||
// The caller should have checked this, just verifying.
|
, fYUVALocations(yuvaLocations)
|
||||||
SkASSERT(fYUVAProxies.isValid());
|
, fYUVColorSpace(colorSpace) {
|
||||||
|
// The caller should have done this work, just verifying
|
||||||
|
SkDEBUGCODE(int textureCount;)
|
||||||
|
SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(fYUVALocations, &textureCount));
|
||||||
|
SkASSERT(textureCount == fNumViews);
|
||||||
|
|
||||||
|
for (int i = 0; i < numViews; ++i) {
|
||||||
|
fViews[i] = std::move(views[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For onMakeColorSpace()
|
// For onMakeColorSpace()
|
||||||
@ -59,46 +71,55 @@ SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
|
|||||||
image->dimensions(),
|
image->dimensions(),
|
||||||
kNeedNewImageUniqueID,
|
kNeedNewImageUniqueID,
|
||||||
kAssumedColorType,
|
kAssumedColorType,
|
||||||
image->alphaType(),
|
// If an alpha channel is present we always switch to kPremul. This is because,
|
||||||
|
// although the planar data is always un-premul, the final interleaved RGB image
|
||||||
|
// is/would-be premul.
|
||||||
|
GetAlphaTypeFromYUVALocations(image->fYUVALocations),
|
||||||
std::move(targetCS))
|
std::move(targetCS))
|
||||||
, fYUVAProxies(image->fYUVAProxies)
|
, fNumViews(image->fNumViews)
|
||||||
, fRGBView(image->fRGBView)
|
, fYUVALocations(image->fYUVALocations)
|
||||||
|
, fYUVColorSpace(image->fYUVColorSpace)
|
||||||
// Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
|
// Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
|
||||||
// image->refColorSpace() into an explicit SRGB.
|
// image->refColorSpace() into an explicit SRGB.
|
||||||
, fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
|
, fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
|
||||||
// We should either have a RGB proxy *or* a set of YUVA proxies.
|
// The caller should have done this work, just verifying
|
||||||
SkASSERT(fYUVAProxies.isValid() != SkToBool(image->fRGBView));
|
SkDEBUGCODE(int textureCount;)
|
||||||
|
SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(image->fYUVALocations, &textureCount));
|
||||||
|
SkASSERT(textureCount == fNumViews);
|
||||||
|
|
||||||
|
if (image->fRGBView.proxy()) {
|
||||||
|
fRGBView = image->fRGBView; // we ref in this case, not move
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < fNumViews; ++i) {
|
||||||
|
fViews[i] = image->fViews[i]; // we ref in this case, not move
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
|
bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
|
||||||
// We shouldn't get here if the planes were already flattened to RGBA.
|
// We shouldn't get here if the planes were already flattened to RGBA.
|
||||||
SkASSERT(fYUVAProxies.isValid() && !fRGBView);
|
SkASSERT(fViews[0].proxy() && !fRGBView.proxy());
|
||||||
if (!context || !fContext->priv().matches(context)) {
|
if (!context || !fContext->priv().matches(context)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
GrSurfaceProxyView newViews[4];
|
||||||
if (!context->priv().caps()->mipmapSupport()) {
|
if (!context->priv().caps()->mipmapSupport()) {
|
||||||
// We succeed in this case by doing nothing.
|
// We succeed in this case by doing nothing.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int n = fYUVAProxies.yuvaInfo().numPlanes();
|
for (int i = 0; i < fNumViews; ++i) {
|
||||||
sk_sp<GrSurfaceProxy> newProxies[4];
|
auto* t = fViews[i].asTextureProxy();
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
auto* t = fYUVAProxies.proxy(i)->asTextureProxy();
|
|
||||||
if (t->mipmapped() == GrMipmapped::kNo && (t->width() > 1 || t->height() > 1)) {
|
if (t->mipmapped() == GrMipmapped::kNo && (t->width() > 1 || t->height() > 1)) {
|
||||||
auto newView = GrCopyBaseMipMapToView(context, fYUVAProxies.makeView(i));
|
if (!(newViews[i] = GrCopyBaseMipMapToView(context, fViews[i]))) {
|
||||||
if (!newView) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SkASSERT(newView.swizzle() == fYUVAProxies.makeView(i).swizzle());
|
|
||||||
newProxies[i] = newView.detachProxy();
|
|
||||||
} else {
|
} else {
|
||||||
newProxies[i] = fYUVAProxies.refProxy(i);
|
newViews[i] = fViews[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fYUVAProxies = GrYUVATextureProxies(fYUVAProxies.yuvaInfo(),
|
for (int i = 0; i < fNumViews; ++i) {
|
||||||
newProxies,
|
fViews[i] = std::move(newViews[i]);
|
||||||
fYUVAProxies.textureOrigin());
|
}
|
||||||
SkASSERT(fYUVAProxies.isValid());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,19 +136,15 @@ GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const
|
|||||||
return GrSemaphoresSubmitted::kNo;
|
return GrSemaphoresSubmitted::kNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSurfaceProxy* proxies[SkYUVAInfo::kMaxPlanes] = {};
|
GrSurfaceProxy* proxies[4] = {fViews[0].proxy(), fViews[1].proxy(), fViews[2].proxy(),
|
||||||
size_t numProxies;
|
fViews[3].proxy()};
|
||||||
if (fRGBView) {
|
size_t numProxies = fNumViews;
|
||||||
|
if (fRGBView.proxy()) {
|
||||||
// Either we've already flushed the flattening draw or the flattening is unflushed. In the
|
// Either we've already flushed the flattening draw or the flattening is unflushed. In the
|
||||||
// latter case it should still be ok to just pass fRGBView proxy because it in turn depends
|
// latter case it should still be ok to just pass fRGBView proxy because it in turn depends
|
||||||
// on the planar proxies and will cause all of their work to flush as well.
|
// on the planar proxies and will cause all of their work to flush as well.
|
||||||
proxies[0] = fRGBView.proxy();
|
proxies[0] = fRGBView.proxy();
|
||||||
numProxies = 1;
|
numProxies = 1;
|
||||||
} else {
|
|
||||||
numProxies = fYUVAProxies.numPlanes();
|
|
||||||
for (size_t i = 0; i < numProxies; ++i) {
|
|
||||||
proxies[i] = fYUVAProxies.proxy(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return dContext->priv().flushSurfaces({proxies, numProxies},
|
return dContext->priv().flushSurfaces({proxies, numProxies},
|
||||||
SkSurface::BackendSurfaceAccess::kNoAccess,
|
SkSurface::BackendSurfaceAccess::kNoAccess,
|
||||||
@ -136,6 +153,49 @@ GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const
|
|||||||
|
|
||||||
GrTextureProxy* SkImage_GpuYUVA::peekProxy() const { return fRGBView.asTextureProxy(); }
|
GrTextureProxy* SkImage_GpuYUVA::peekProxy() const { return fRGBView.asTextureProxy(); }
|
||||||
|
|
||||||
|
bool SkImage_GpuYUVA::MakeTempTextureProxies(GrRecordingContext* rContext,
|
||||||
|
const GrBackendTexture yuvaTextures[],
|
||||||
|
int numTextures,
|
||||||
|
const SkYUVAInfo::YUVALocations& yuvaLocations,
|
||||||
|
GrSurfaceOrigin imageOrigin,
|
||||||
|
GrSurfaceProxyView tempViews[4],
|
||||||
|
sk_sp<GrRefCntedCallback> releaseHelper) {
|
||||||
|
GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
|
||||||
|
for (int textureIndex = 0; textureIndex < numTextures; ++textureIndex) {
|
||||||
|
const GrBackendFormat& backendFormat = yuvaTextures[textureIndex].getBackendFormat();
|
||||||
|
if (!backendFormat.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkASSERT(yuvaTextures[textureIndex].isValid());
|
||||||
|
|
||||||
|
auto proxy = proxyProvider->wrapBackendTexture(yuvaTextures[textureIndex],
|
||||||
|
kBorrow_GrWrapOwnership,
|
||||||
|
GrWrapCacheable::kNo,
|
||||||
|
kRead_GrIOType,
|
||||||
|
releaseHelper);
|
||||||
|
if (!proxy) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tempViews[textureIndex] =
|
||||||
|
GrSurfaceProxyView(std::move(proxy), imageOrigin, GrSwizzle("rgba"));
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
// Check that each texture contains the channel data for the corresponding YUVA location
|
||||||
|
auto formatChannelMask = backendFormat.channelMask();
|
||||||
|
if (formatChannelMask & kGray_SkColorChannelFlag) {
|
||||||
|
formatChannelMask |= kRGB_SkColorChannelFlags;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
|
||||||
|
if (yuvaLocations[i].fPlane == textureIndex) {
|
||||||
|
uint32_t channelAsMask = 1 << static_cast<int>(yuvaLocations[i].fChannel);
|
||||||
|
SkASSERT(channelAsMask & formatChannelMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context) const {
|
void SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context) const {
|
||||||
if (fRGBView.proxy()) {
|
if (fRGBView.proxy()) {
|
||||||
return;
|
return;
|
||||||
@ -162,18 +222,23 @@ void SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context) const {
|
|||||||
|
|
||||||
const GrCaps& caps = *context->priv().caps();
|
const GrCaps& caps = *context->priv().caps();
|
||||||
|
|
||||||
auto fp = GrYUVtoRGBEffect::Make(fYUVAProxies, GrSamplerState::Filter::kNearest, caps);
|
auto fp = GrYUVtoRGBEffect::Make(
|
||||||
|
fViews, fYUVALocations, fYUVColorSpace, GrSamplerState::Filter::kNearest, caps);
|
||||||
if (fFromColorSpace) {
|
if (fFromColorSpace) {
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
auto colorSpaceXform = GrColorSpaceXform::Make(fFromColorSpace.get(),
|
||||||
fFromColorSpace.get(), this->alphaType(),
|
this->alphaType(),
|
||||||
this->colorSpace(), this->alphaType());
|
this->colorSpace(),
|
||||||
|
this->alphaType());
|
||||||
|
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(colorSpaceXform));
|
||||||
}
|
}
|
||||||
|
|
||||||
surfaceFillContext->fillWithFP(std::move(fp));
|
surfaceFillContext->fillWithFP(std::move(fp));
|
||||||
|
|
||||||
fRGBView = surfaceFillContext->readSurfaceView();
|
fRGBView = surfaceFillContext->readSurfaceView();
|
||||||
SkASSERT(fRGBView.swizzle() == GrSwizzle());
|
SkASSERT(fRGBView.swizzle() == GrSwizzle());
|
||||||
fYUVAProxies = {};
|
for (auto& v : fViews) {
|
||||||
|
v.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSurfaceProxyView SkImage_GpuYUVA::refMippedView(GrRecordingContext* context) const {
|
GrSurfaceProxyView SkImage_GpuYUVA::refMippedView(GrRecordingContext* context) const {
|
||||||
@ -221,7 +286,9 @@ sk_sp<SkImage> SkImage_GpuYUVA::onMakeColorTypeAndColorSpace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
|
sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
|
||||||
return sk_sp<SkImage>(new SkImage_GpuYUVA(fContext, this, std::move(newCS)));
|
return sk_make_sp<SkImage_GpuYUVA>(fContext, this->dimensions(), kNeedNewImageUniqueID,
|
||||||
|
fYUVColorSpace, fViews, fNumViews, fYUVALocations,
|
||||||
|
std::move(newCS));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -233,36 +300,32 @@ sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrRecordingContext* context,
|
|||||||
ReleaseContext releaseContext) {
|
ReleaseContext releaseContext) {
|
||||||
auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
|
auto releaseHelper = GrRefCntedCallback::Make(textureReleaseProc, releaseContext);
|
||||||
|
|
||||||
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
|
SkYUVAInfo::YUVALocations yuvaLocations = yuvaTextures.toYUVALocations();
|
||||||
int numPlanes = yuvaTextures.yuvaInfo().numPlanes();
|
|
||||||
sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes];
|
|
||||||
for (int plane = 0; plane < numPlanes; ++plane) {
|
|
||||||
proxies[plane] = proxyProvider->wrapBackendTexture(yuvaTextures.texture(plane),
|
|
||||||
kBorrow_GrWrapOwnership,
|
|
||||||
GrWrapCacheable::kNo,
|
|
||||||
kRead_GrIOType,
|
|
||||||
releaseHelper);
|
|
||||||
if (!proxies[plane]) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GrYUVATextureProxies yuvaProxies(yuvaTextures.yuvaInfo(),
|
|
||||||
proxies,
|
|
||||||
yuvaTextures.textureOrigin());
|
|
||||||
|
|
||||||
if (!yuvaProxies.isValid()) {
|
GrSurfaceProxyView tempViews[4];
|
||||||
|
if (!SkImage_GpuYUVA::MakeTempTextureProxies(context,
|
||||||
|
yuvaTextures.textures().data(),
|
||||||
|
yuvaTextures.numPlanes(),
|
||||||
|
yuvaLocations,
|
||||||
|
yuvaTextures.textureOrigin(),
|
||||||
|
tempViews,
|
||||||
|
std::move(releaseHelper))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
|
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
|
||||||
|
yuvaTextures.yuvaInfo().dimensions(),
|
||||||
kNeedNewImageUniqueID,
|
kNeedNewImageUniqueID,
|
||||||
yuvaProxies,
|
yuvaTextures.yuvaInfo().yuvColorSpace(),
|
||||||
|
tempViews,
|
||||||
|
yuvaTextures.numPlanes(),
|
||||||
|
yuvaLocations,
|
||||||
imageColorSpace);
|
imageColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
|
sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
|
||||||
const SkYUVAPixmaps& pixmaps,
|
const SkYUVAPixmaps& pixmaps,
|
||||||
GrMipmapped buildMips,
|
GrMipMapped buildMips,
|
||||||
bool limitToMaxTextureSize,
|
bool limitToMaxTextureSize,
|
||||||
sk_sp<SkColorSpace> imageColorSpace) {
|
sk_sp<SkColorSpace> imageColorSpace) {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
@ -273,6 +336,8 @@ sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkYUVAInfo::YUVALocations yuvaLocations = pixmaps.toYUVALocations();
|
||||||
|
|
||||||
// SkImage_GpuYUVA doesn't yet support different encoded origins.
|
// SkImage_GpuYUVA doesn't yet support different encoded origins.
|
||||||
if (pixmaps.yuvaInfo().origin() != kTopLeft_SkEncodedOrigin) {
|
if (pixmaps.yuvaInfo().origin() != kTopLeft_SkEncodedOrigin) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -282,58 +347,45 @@ sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
|
|||||||
buildMips = GrMipMapped::kNo;
|
buildMips = GrMipMapped::kNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the pixmaps if necessary.
|
// Make proxies
|
||||||
|
GrSurfaceProxyView tempViews[4];
|
||||||
int numPlanes = pixmaps.numPlanes();
|
int numPlanes = pixmaps.numPlanes();
|
||||||
int maxTextureSize = context->priv().caps()->maxTextureSize();
|
int maxTextureSize = context->priv().caps()->maxTextureSize();
|
||||||
int maxDim = std::max(pixmaps.yuvaInfo().width(), pixmaps.yuvaInfo().height());
|
for (int i = 0; i < numPlanes; ++i) {
|
||||||
|
const SkPixmap* pixmap = &pixmaps.plane(i);
|
||||||
SkYUVAPixmaps tempPixmaps;
|
SkAutoPixmapStorage resized;
|
||||||
const SkYUVAPixmaps* pixmapsToUpload = &pixmaps;
|
int maxDim = std::max(pixmap->width(), pixmap->height());
|
||||||
// We assume no plane is larger than the image size (and at least one plane is as big).
|
if (maxDim > maxTextureSize) {
|
||||||
if (maxDim > maxTextureSize) {
|
if (!limitToMaxTextureSize) {
|
||||||
if (!limitToMaxTextureSize) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
float scale = static_cast<float>(maxTextureSize)/maxDim;
|
|
||||||
SkISize newDimensions = {
|
|
||||||
std::min(static_cast<int>(pixmaps.yuvaInfo().width() *scale), maxTextureSize),
|
|
||||||
std::min(static_cast<int>(pixmaps.yuvaInfo().height()*scale), maxTextureSize)
|
|
||||||
};
|
|
||||||
SkYUVAInfo newInfo = pixmaps.yuvaInfo().makeDimensions(newDimensions);
|
|
||||||
SkYUVAPixmapInfo newPixmapInfo(newInfo, pixmaps.dataType(), /*row bytes*/ nullptr);
|
|
||||||
tempPixmaps = SkYUVAPixmaps::Allocate(newPixmapInfo);
|
|
||||||
SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNone);
|
|
||||||
if (!tempPixmaps.isValid()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < numPlanes; ++i) {
|
|
||||||
if (!pixmaps.plane(i).scalePixels(tempPixmaps.plane(i), sampling)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
float scale = static_cast<float>(maxTextureSize)/maxDim;
|
||||||
|
int newWidth = std::min(static_cast<int>(pixmap->width() *scale), maxTextureSize);
|
||||||
|
int newHeight = std::min(static_cast<int>(pixmap->height()*scale), maxTextureSize);
|
||||||
|
SkImageInfo info = pixmap->info().makeWH(newWidth, newHeight);
|
||||||
|
SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNone);
|
||||||
|
if (!resized.tryAlloc(info) || !pixmap->scalePixels(resized, sampling)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
pixmap = &resized;
|
||||||
}
|
}
|
||||||
pixmapsToUpload = &tempPixmaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to texture proxies.
|
|
||||||
GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
|
|
||||||
GrColorType pixmapColorTypes[SkYUVAInfo::kMaxPlanes];
|
|
||||||
for (int i = 0; i < numPlanes; ++i) {
|
|
||||||
// Turn the pixmap into a GrTextureProxy
|
// Turn the pixmap into a GrTextureProxy
|
||||||
SkBitmap bmp;
|
SkBitmap bmp;
|
||||||
bmp.installPixels(pixmapsToUpload->plane(i));
|
bmp.installPixels(*pixmap);
|
||||||
GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
|
GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
|
||||||
views[i] = bitmapMaker.view(buildMips);
|
tempViews[i] = bitmapMaker.view(buildMips);
|
||||||
if (!views[i]) {
|
if (!tempViews[i]) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pixmapColorTypes[i] = SkColorTypeToGrColorType(bmp.colorType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrYUVATextureProxies yuvaProxies(pixmapsToUpload->yuvaInfo(), views, pixmapColorTypes);
|
|
||||||
SkASSERT(yuvaProxies.isValid());
|
|
||||||
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
|
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
|
||||||
|
pixmaps.yuvaInfo().dimensions(),
|
||||||
kNeedNewImageUniqueID,
|
kNeedNewImageUniqueID,
|
||||||
std::move(yuvaProxies),
|
pixmaps.yuvaInfo().yuvColorSpace(),
|
||||||
|
tempViews,
|
||||||
|
numPlanes,
|
||||||
|
yuvaLocations,
|
||||||
std::move(imageColorSpace));
|
std::move(imageColorSpace));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,6 +413,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
|
|||||||
releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
|
releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkYUVAInfo::YUVALocations yuvaLocations = yuvaBackendTextureInfo.toYUVALocations();
|
||||||
if (yuvaBackendTextureInfo.yuvaInfo().origin() != SkEncodedOrigin::kDefault_SkEncodedOrigin) {
|
if (yuvaBackendTextureInfo.yuvaInfo().origin() != SkEncodedOrigin::kDefault_SkEncodedOrigin) {
|
||||||
// SkImage_GpuYUVA does not support this yet. This will get removed
|
// SkImage_GpuYUVA does not support this yet. This will get removed
|
||||||
// when the old APIs are gone and we only have to support YUVA configs described by
|
// when the old APIs are gone and we only have to support YUVA configs described by
|
||||||
@ -381,24 +434,23 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a lazy proxy for each plane and wrap in a view.
|
// Make a lazy proxy for each plane and wrap in a view.
|
||||||
sk_sp<GrSurfaceProxy> proxies[4];
|
GrSurfaceProxyView views[4];
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int texIdx = 0; texIdx < n; ++texIdx) {
|
||||||
proxies[i] = MakePromiseImageLazyProxy(context,
|
auto proxy = MakePromiseImageLazyProxy(context,
|
||||||
planeDimensions[i],
|
planeDimensions[texIdx],
|
||||||
yuvaBackendTextureInfo.planeFormat(i),
|
yuvaBackendTextureInfo.planeFormat(texIdx),
|
||||||
GrMipmapped::kNo,
|
GrMipmapped::kNo,
|
||||||
textureFulfillProc,
|
textureFulfillProc,
|
||||||
std::move(releaseHelpers[i]));
|
std::move(releaseHelpers[texIdx]));
|
||||||
if (!proxies[i]) {
|
if (!proxy) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
views[texIdx] = GrSurfaceProxyView(std::move(proxy), yuvaBackendTextureInfo.textureOrigin(),
|
||||||
|
GrSwizzle("rgba"));
|
||||||
}
|
}
|
||||||
GrYUVATextureProxies yuvaTextureProxies(yuvaBackendTextureInfo.yuvaInfo(),
|
|
||||||
proxies,
|
return sk_make_sp<SkImage_GpuYUVA>(
|
||||||
yuvaBackendTextureInfo.textureOrigin());
|
sk_ref_sp(context), yuvaBackendTextureInfo.yuvaInfo().dimensions(),
|
||||||
SkASSERT(yuvaTextureProxies.isValid());
|
kNeedNewImageUniqueID, yuvaBackendTextureInfo.yuvColorSpace(), views, n, yuvaLocations,
|
||||||
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
|
std::move(imageColorSpace));
|
||||||
kNeedNewImageUniqueID,
|
|
||||||
std::move(yuvaTextureProxies),
|
|
||||||
std::move(imageColorSpace));
|
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,13 @@
|
|||||||
|
|
||||||
#include "include/gpu/GrBackendSurface.h"
|
#include "include/gpu/GrBackendSurface.h"
|
||||||
#include "src/core/SkCachedData.h"
|
#include "src/core/SkCachedData.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/image/SkImage_GpuBase.h"
|
#include "src/image/SkImage_GpuBase.h"
|
||||||
|
|
||||||
class GrDirectContext;
|
class GrDirectContext;
|
||||||
class GrRecordingContext;
|
class GrRecordingContext;
|
||||||
class GrTexture;
|
class GrTexture;
|
||||||
|
|
||||||
// Wraps the 1 to 4 planes of a YUVA image for consumption by the GPU.
|
// 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.
|
// Initially any direct rendering will be done by passing the individual planes to a shader.
|
||||||
// Once any method requests a flattened image (e.g., onReadPixels), the flattened RGB
|
// Once any method requests a flattened image (e.g., onReadPixels), the flattened RGB
|
||||||
// proxy will be stored and used for any future rendering.
|
// proxy will be stored and used for any future rendering.
|
||||||
@ -26,8 +25,12 @@ public:
|
|||||||
friend class GrYUVAImageTextureMaker;
|
friend class GrYUVAImageTextureMaker;
|
||||||
|
|
||||||
SkImage_GpuYUVA(sk_sp<GrImageContext>,
|
SkImage_GpuYUVA(sk_sp<GrImageContext>,
|
||||||
|
SkISize size,
|
||||||
uint32_t uniqueID,
|
uint32_t uniqueID,
|
||||||
GrYUVATextureProxies proxies,
|
SkYUVColorSpace,
|
||||||
|
GrSurfaceProxyView views[],
|
||||||
|
int numViews,
|
||||||
|
const SkYUVAInfo::YUVALocations&,
|
||||||
sk_sp<SkColorSpace>);
|
sk_sp<SkColorSpace>);
|
||||||
|
|
||||||
GrSemaphoresSubmitted onFlush(GrDirectContext*, const GrFlushInfo&) override;
|
GrSemaphoresSubmitted onFlush(GrDirectContext*, const GrFlushInfo&) override;
|
||||||
@ -39,8 +42,7 @@ public:
|
|||||||
const GrSurfaceProxyView* view(GrRecordingContext* context) const override;
|
const GrSurfaceProxyView* view(GrRecordingContext* context) const override;
|
||||||
|
|
||||||
bool onIsTextureBacked() const override {
|
bool onIsTextureBacked() const override {
|
||||||
// We should have YUVA proxies or a RGBA proxy,but not both.
|
SkASSERT(fViews[0].proxy() || fRGBView.proxy());
|
||||||
SkASSERT(fYUVAProxies.isValid() != SkToBool(fRGBView));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ public:
|
|||||||
#if GR_TEST_UTILS
|
#if GR_TEST_UTILS
|
||||||
bool testingOnly_IsFlattened() const {
|
bool testingOnly_IsFlattened() const {
|
||||||
// We should only have the flattened proxy or the planar proxies at one point in time.
|
// We should only have the flattened proxy or the planar proxies at one point in time.
|
||||||
SkASSERT(SkToBool(fRGBView) != fYUVAProxies.isValid());
|
SkASSERT(SkToBool(fRGBView.proxy()) != SkToBool(fViews[0].proxy()));
|
||||||
return SkToBool(fRGBView.proxy());
|
return SkToBool(fRGBView.proxy());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -74,17 +76,25 @@ public:
|
|||||||
PromiseImageTextureReleaseProc textureReleaseProc,
|
PromiseImageTextureReleaseProc textureReleaseProc,
|
||||||
PromiseImageTextureContext textureContexts[]);
|
PromiseImageTextureContext textureContexts[]);
|
||||||
|
|
||||||
|
static bool MakeTempTextureProxies(GrRecordingContext*,
|
||||||
|
const GrBackendTexture yuvaTextures[],
|
||||||
|
int numTextures,
|
||||||
|
const SkYUVAInfo::YUVALocations&,
|
||||||
|
GrSurfaceOrigin imageOrigin,
|
||||||
|
GrSurfaceProxyView tempViews[4],
|
||||||
|
sk_sp<GrRefCntedCallback> releaseHelper);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkImage_GpuYUVA(sk_sp<GrImageContext>, const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
|
SkImage_GpuYUVA(sk_sp<GrImageContext>, const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
|
||||||
|
|
||||||
void flattenToRGB(GrRecordingContext*) const;
|
void flattenToRGB(GrRecordingContext*) const;
|
||||||
|
|
||||||
mutable GrYUVATextureProxies fYUVAProxies;
|
// This array will usually only be sparsely populated.
|
||||||
|
// The actual non-null fields are dictated by the 'fYUVAIndices' indices
|
||||||
// This is only allocated when the image needs to be flattened rather than
|
mutable GrSurfaceProxyView fViews[4];
|
||||||
// using the separate YUVA planes. From thence forth we will only use the
|
int fNumViews;
|
||||||
// the RGBView.
|
SkYUVAInfo::YUVALocations fYUVALocations;
|
||||||
mutable GrSurfaceProxyView fRGBView;
|
const SkYUVColorSpace fYUVColorSpace;
|
||||||
|
|
||||||
// If this is non-null then the planar data should be converted from fFromColorSpace to
|
// If this is non-null then the planar data should be converted from fFromColorSpace to
|
||||||
// this->colorSpace(). Otherwise we assume the planar data (post YUV->RGB conversion) is already
|
// this->colorSpace(). Otherwise we assume the planar data (post YUV->RGB conversion) is already
|
||||||
@ -96,6 +106,10 @@ private:
|
|||||||
mutable sk_sp<SkColorSpace> fOnMakeColorSpaceTarget;
|
mutable sk_sp<SkColorSpace> fOnMakeColorSpaceTarget;
|
||||||
mutable sk_sp<SkImage> fOnMakeColorSpaceResult;
|
mutable sk_sp<SkImage> fOnMakeColorSpaceResult;
|
||||||
|
|
||||||
|
// This is only allocated when the image needs to be flattened rather than
|
||||||
|
// using the separate YUVA planes. From thence forth we will only use the
|
||||||
|
// the RGBView.
|
||||||
|
mutable GrSurfaceProxyView fRGBView;
|
||||||
using INHERITED = SkImage_GpuBase;
|
using INHERITED = SkImage_GpuBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@
|
|||||||
#include "src/gpu/GrProxyProvider.h"
|
#include "src/gpu/GrProxyProvider.h"
|
||||||
#include "src/gpu/GrRecordingContextPriv.h"
|
#include "src/gpu/GrRecordingContextPriv.h"
|
||||||
#include "src/gpu/GrSamplerState.h"
|
#include "src/gpu/GrSamplerState.h"
|
||||||
#include "src/gpu/GrSurfaceFillContext.h"
|
#include "src/gpu/GrSurfaceDrawContext.h"
|
||||||
#include "src/gpu/GrYUVATextureProxies.h"
|
|
||||||
#include "src/gpu/SkGr.h"
|
#include "src/gpu/SkGr.h"
|
||||||
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
|
||||||
#endif
|
#endif
|
||||||
@ -268,8 +267,7 @@ GrSurfaceProxyView SkImage_Lazy::textureProxyViewFromPlanes(GrRecordingContext*
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
|
GrSurfaceProxyView yuvViews[SkYUVAInfo::kMaxPlanes];
|
||||||
GrColorType pixmapColorTypes[SkYUVAInfo::kMaxPlanes];
|
|
||||||
for (int i = 0; i < yuvaPixmaps.numPlanes(); ++i) {
|
for (int i = 0; i < yuvaPixmaps.numPlanes(); ++i) {
|
||||||
// If the sizes of the components are not all the same we choose to create exact-match
|
// 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.
|
// textures for the smaller ones rather than add a texture domain to the draw.
|
||||||
@ -298,12 +296,11 @@ GrSurfaceProxyView SkImage_Lazy::textureProxyViewFromPlanes(GrRecordingContext*
|
|||||||
bitmap.setImmutable();
|
bitmap.setImmutable();
|
||||||
|
|
||||||
GrBitmapTextureMaker maker(ctx, bitmap, fit);
|
GrBitmapTextureMaker maker(ctx, bitmap, fit);
|
||||||
views[i] = maker.view(GrMipmapped::kNo);
|
yuvViews[i] = maker.view(GrMipmapped::kNo);
|
||||||
|
|
||||||
if (!views[i]) {
|
if (!yuvViews[i]) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
pixmapColorTypes[i] = SkColorTypeToGrColorType(bitmap.colorType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: investigate preallocating mip maps here
|
// TODO: investigate preallocating mip maps here
|
||||||
@ -323,13 +320,12 @@ GrSurfaceProxyView SkImage_Lazy::textureProxyViewFromPlanes(GrRecordingContext*
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
GrYUVATextureProxies yuvaProxies(yuvaPixmaps.yuvaInfo(), views, pixmapColorTypes);
|
std::unique_ptr<GrFragmentProcessor> yuvToRgbProcessor =
|
||||||
SkAssertResult(yuvaProxies.isValid());
|
GrYUVtoRGBEffect::Make(yuvViews,
|
||||||
|
yuvaPixmaps.toYUVALocations(),
|
||||||
std::unique_ptr<GrFragmentProcessor> fp = GrYUVtoRGBEffect::Make(
|
yuvaPixmaps.yuvaInfo().yuvColorSpace(),
|
||||||
yuvaProxies,
|
GrSamplerState::Filter::kNearest,
|
||||||
GrSamplerState::Filter::kNearest,
|
*ctx->priv().caps());
|
||||||
*ctx->priv().caps());
|
|
||||||
|
|
||||||
// The pixels after yuv->rgb will be in the generator's color space.
|
// The pixels after yuv->rgb will be in the generator's color space.
|
||||||
// If onMakeColorTypeAndColorSpace has been called then this will not match this image's
|
// If onMakeColorTypeAndColorSpace has been called then this will not match this image's
|
||||||
@ -344,11 +340,18 @@ GrSurfaceProxyView SkImage_Lazy::textureProxyViewFromPlanes(GrRecordingContext*
|
|||||||
|
|
||||||
// If the caller expects the pixels in a different color space than the one from the image,
|
// If the caller expects the pixels in a different color space than the one from the image,
|
||||||
// apply a color conversion to do this.
|
// apply a color conversion to do this.
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
std::unique_ptr<GrFragmentProcessor> colorConversionProcessor =
|
||||||
srcColorSpace, kOpaque_SkAlphaType,
|
GrColorSpaceXformEffect::Make(std::move(yuvToRgbProcessor),
|
||||||
dstColorSpace, kOpaque_SkAlphaType);
|
srcColorSpace, kOpaque_SkAlphaType,
|
||||||
surfaceFillContext->fillWithFP(std::move(fp));
|
dstColorSpace, kOpaque_SkAlphaType);
|
||||||
|
SkMatrix m = SkEncodedOriginToMatrix(yuvaPixmaps.yuvaInfo().origin(),
|
||||||
|
this->width(),
|
||||||
|
this->height());
|
||||||
|
// The returned matrix is a view matrix but we need a local matrix.
|
||||||
|
SkAssertResult(m.invert(&m));
|
||||||
|
surfaceFillContext->fillWithFP(m, std::move(colorConversionProcessor));
|
||||||
|
|
||||||
|
SkASSERT(surfaceFillContext->asTextureProxy());
|
||||||
return surfaceFillContext->readSurfaceView();
|
return surfaceFillContext->readSurfaceView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user