Reland "Make GrDirectContext::updateBackendTexture handle pixmaps with non-type row bytes."
This is a reland of 07d8c0d11c
Original change's description:
> Make GrDirectContext::updateBackendTexture handle pixmaps with non-type row bytes.
>
> Some GL contexts don't support GL_UNPACK_ROW_LENGTH and we must
> copy the src data to a pixmap with tight row bytes.
>
> Bug: chromium:1170392
>
> Change-Id: I4590f20dbc80cb792f30f0059536716cf106f6c3
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/361717
> Reviewed-by: Robert Phillips <robertphillips@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
Bug: chromium:1170392
Change-Id: I6fb759c35f86d816b16694b00edaa1116a446d15
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/363099
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
4b09de3c90
commit
759217eb94
@ -286,6 +286,11 @@ struct SK_API GrContextOptions {
|
||||
*/
|
||||
bool fRandomGLOOM = false;
|
||||
|
||||
/**
|
||||
* Force off support for write pixels row bytes in caps.
|
||||
*/
|
||||
bool fDisallowWritePixelRowBytes = false;
|
||||
|
||||
/**
|
||||
* Include or exclude specific GPU path renderers.
|
||||
*/
|
||||
|
@ -149,6 +149,9 @@ void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
|
||||
if (options.fClearAllTextures) {
|
||||
fShouldInitializeTextures = true;
|
||||
}
|
||||
if (options.fDisallowWritePixelRowBytes) {
|
||||
fWritePixelsRowBytesSupport = false;
|
||||
}
|
||||
#endif
|
||||
if (options.fSuppressMipmapSupport) {
|
||||
fMipmapSupport = false;
|
||||
|
@ -505,26 +505,34 @@ static bool update_texture_with_pixmaps(GrGpu* gpu,
|
||||
const GrBackendTexture& backendTexture,
|
||||
GrSurfaceOrigin textureOrigin,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) {
|
||||
bool flip = textureOrigin == kBottomLeft_GrSurfaceOrigin;
|
||||
bool mustBeTight = !gpu->caps()->writePixelsRowBytesSupport();
|
||||
|
||||
size_t size = 0;
|
||||
for (int i = 0; i < numLevels; ++i) {
|
||||
size_t minRowBytes = srcData[i].info().minRowBytes();
|
||||
if (flip || (mustBeTight && srcData[i].rowBytes() != minRowBytes)) {
|
||||
size += minRowBytes * srcData[i].height();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> tempStorage;
|
||||
SkAutoSTArray<15, GrPixmap> tempPixmaps(numLevels);
|
||||
if (textureOrigin == kBottomLeft_GrSurfaceOrigin) {
|
||||
size_t size = 0;
|
||||
for (int i = 0; i < numLevels; ++i) {
|
||||
size += srcData[i].info().minRowBytes()*srcData[i].height();
|
||||
}
|
||||
if (size) {
|
||||
tempStorage.reset(new char[size]);
|
||||
size = 0;
|
||||
for (int i = 0; i < numLevels; ++i) {
|
||||
size_t tempRB = srcData[i].info().minRowBytes();
|
||||
tempPixmaps[i] = {srcData[i].info(), tempStorage.get() + size, tempRB};
|
||||
SkAssertResult(GrConvertPixels(tempPixmaps[i], srcData[i], /*flip*/ true));
|
||||
size += tempRB*srcData[i].height();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < numLevels; ++i) {
|
||||
}
|
||||
size = 0;
|
||||
SkAutoSTArray<15, GrPixmap> tempPixmaps(numLevels);
|
||||
for (int i = 0; i < numLevels; ++i) {
|
||||
size_t minRowBytes = srcData[i].info().minRowBytes();
|
||||
if (flip || (mustBeTight && srcData[i].rowBytes() != minRowBytes)) {
|
||||
tempPixmaps[i] = {srcData[i].info(), tempStorage.get() + size, minRowBytes};
|
||||
SkAssertResult(GrConvertPixels(tempPixmaps[i], srcData[i], flip));
|
||||
size += minRowBytes*srcData[i].height();
|
||||
} else {
|
||||
tempPixmaps[i] = srcData[i];
|
||||
}
|
||||
}
|
||||
|
||||
GrGpu::BackendTextureData data(tempPixmaps.get());
|
||||
return gpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
|
||||
}
|
||||
|
@ -3692,7 +3692,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
|
||||
}
|
||||
|
||||
#ifndef SK_BUILD_FOR_IOS
|
||||
if (kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) {
|
||||
if (ctxInfo.renderer() == kPowerVRRogue_GrGLRenderer) {
|
||||
// We saw this bug on a TecnoSpark 3 Pro with a PowerVR GE8300.
|
||||
// GL_VERSION: "OpenGL ES 3.2 build 1.10@51309121"
|
||||
// Possibly this could be more limited by driver version or HW generation.
|
||||
@ -3702,6 +3702,11 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
|
||||
// base level, max level, etc.). Currently we just set the min filter level every time we
|
||||
// bind a texture as the workaround.
|
||||
fMustSetAnyTexParameterToEnableMipmapping = true;
|
||||
// ColorTypeBackendAllocationTest failed for kAlpha_8 and kGray_8 when using
|
||||
// GL_UNPACK_ROW_LENGTH. Perhaps this could be a more limited workaround by applying
|
||||
// only to single channel 8 bit unorm formats but we only have a monolithic query for this
|
||||
// support at present.
|
||||
fWritePixelsRowBytesSupport = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -425,16 +425,31 @@ static void check_mipmaps(GrDirectContext* dContext,
|
||||
}
|
||||
}
|
||||
|
||||
static int make_pixmaps(SkColorType skColorType, GrMipmapped mipMapped,
|
||||
const SkColor4f colors[6], SkAutoPixmapStorage pixmaps[6]) {
|
||||
static int make_pixmaps(SkColorType skColorType,
|
||||
GrMipmapped mipmapped,
|
||||
const SkColor4f colors[6],
|
||||
SkPixmap pixmaps[6],
|
||||
std::unique_ptr<char[]>* mem) {
|
||||
int levelSize = 32;
|
||||
int numMipLevels = mipMapped == GrMipmapped::kYes ? 6 : 1;
|
||||
int numMipLevels = mipmapped == GrMipmapped::kYes ? 6 : 1;
|
||||
size_t size = 0;
|
||||
SkImageInfo ii[6];
|
||||
size_t rowBytes[6];
|
||||
for (int level = 0; level < numMipLevels; ++level) {
|
||||
SkImageInfo ii = SkImageInfo::Make(levelSize,
|
||||
levelSize,
|
||||
skColorType,
|
||||
kUnpremul_SkAlphaType);
|
||||
pixmaps[level].alloc(ii);
|
||||
ii[level] = SkImageInfo::Make(levelSize, levelSize, skColorType, kUnpremul_SkAlphaType);
|
||||
rowBytes[level] = ii[level].minRowBytes();
|
||||
// Make sure we test row bytes that aren't tight.
|
||||
if (!(level % 2)) {
|
||||
rowBytes[level] += (level + 1)*SkColorTypeBytesPerPixel(ii[level].colorType());
|
||||
}
|
||||
size += rowBytes[level]*ii[level].height();
|
||||
levelSize /= 2;
|
||||
}
|
||||
mem->reset(new char[size]);
|
||||
char* addr = mem->get();
|
||||
for (int level = 0; level < numMipLevels; ++level) {
|
||||
pixmaps[level].reset(ii[level], addr, rowBytes[level]);
|
||||
addr += rowBytes[level]*ii[level].height();
|
||||
pixmaps[level].erase(colors[level]);
|
||||
levelSize /= 2;
|
||||
}
|
||||
@ -451,9 +466,10 @@ static void test_pixmap_init(GrDirectContext* dContext,
|
||||
GrRenderable)> create,
|
||||
SkColorType skColorType,
|
||||
GrSurfaceOrigin origin,
|
||||
GrMipmapped mipMapped,
|
||||
GrMipmapped mipmapped,
|
||||
GrRenderable renderable) {
|
||||
SkAutoPixmapStorage pixmapMem[6];
|
||||
SkPixmap pixmaps[6];
|
||||
std::unique_ptr<char[]> memForPixmaps;
|
||||
SkColor4f colors[6] = {
|
||||
{ 1.0f, 0.0f, 0.0f, 1.0f }, // R
|
||||
{ 0.0f, 1.0f, 0.0f, 0.9f }, // G
|
||||
@ -463,15 +479,9 @@ static void test_pixmap_init(GrDirectContext* dContext,
|
||||
{ 1.0f, 1.0f, 0.0f, 0.2f }, // Y
|
||||
};
|
||||
|
||||
int numMipLevels = make_pixmaps(skColorType, mipMapped, colors, pixmapMem);
|
||||
int numMipLevels = make_pixmaps(skColorType, mipmapped, colors, pixmaps, &memForPixmaps);
|
||||
SkASSERT(numMipLevels);
|
||||
|
||||
// TODO: this is tedious. Should we pass in an array of SkBitmaps instead?
|
||||
SkPixmap pixmaps[6];
|
||||
for (int i = 0; i < numMipLevels; ++i) {
|
||||
pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
|
||||
}
|
||||
|
||||
sk_sp<ManagedBackendTexture> mbet = create(dContext, pixmaps, numMipLevels, origin, renderable);
|
||||
if (!mbet) {
|
||||
// errors here should be reported by the test_wrapping test
|
||||
@ -485,7 +495,7 @@ static void test_pixmap_init(GrDirectContext* dContext,
|
||||
|
||||
auto checkBackendTexture = [&](SkColor4f colors[6]) {
|
||||
GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
|
||||
if (mipMapped == GrMipmapped::kYes) {
|
||||
if (mipmapped == GrMipmapped::kYes) {
|
||||
SkColor4f expectedColors[6] = {
|
||||
get_expected_color(colors[0], grColorType),
|
||||
get_expected_color(colors[1], grColorType),
|
||||
@ -514,10 +524,7 @@ static void test_pixmap_init(GrDirectContext* dContext,
|
||||
{0.0f, 1.0f, 1.0f, 0.5f}, // C
|
||||
{1.0f, 0.0f, 1.0f, 0.3f}, // M
|
||||
};
|
||||
make_pixmaps(skColorType, mipMapped, colorsNew, pixmapMem);
|
||||
for (int i = 0; i < numMipLevels; ++i) {
|
||||
pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
|
||||
}
|
||||
make_pixmaps(skColorType, mipmapped, colorsNew, pixmaps, &memForPixmaps);
|
||||
|
||||
// Upload new data and make sure everything still works
|
||||
dContext->updateBackendTexture(mbet->texture(),
|
||||
@ -560,7 +567,8 @@ void check_vk_layout(const GrBackendTexture& backendTex, VkLayout layout) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctxInfo) {
|
||||
void color_type_backend_allocation_test(const sk_gpu_test::ContextInfo& ctxInfo,
|
||||
skiatest::Reporter* reporter) {
|
||||
auto context = ctxInfo.directContext();
|
||||
const GrCaps* caps = context->priv().caps();
|
||||
|
||||
@ -718,6 +726,31 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST(ColorTypeBackendAllocationTest, reporter, options) {
|
||||
for (int t = 0; t < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++t) {
|
||||
auto type = static_cast<sk_gpu_test::GrContextFactory::ContextType>(t);
|
||||
if (!sk_gpu_test::GrContextFactory::IsRenderingContext(type)) {
|
||||
continue;
|
||||
}
|
||||
sk_gpu_test::GrContextFactory factory(options);
|
||||
sk_gpu_test::ContextInfo info = factory.getContextInfo(type);
|
||||
if (!info.directContext()) {
|
||||
continue;
|
||||
}
|
||||
color_type_backend_allocation_test(info, reporter);
|
||||
// The GL backend must support contexts that don't allow GL_UNPACK_ROW_LENGTH. Other
|
||||
// backends are not required to work with this cap disabled.
|
||||
if (info.directContext()->priv().caps()->writePixelsRowBytesSupport() &&
|
||||
info.directContext()->backend() == GrBackendApi::kOpenGL) {
|
||||
GrContextOptions overrideOptions = options;
|
||||
overrideOptions.fDisallowWritePixelRowBytes = true;
|
||||
sk_gpu_test::GrContextFactory overrideFactory(overrideOptions);
|
||||
info = overrideFactory.getContextInfo(type);
|
||||
color_type_backend_allocation_test(info, reporter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef SK_GL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user