Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ac09f7c

Browse files
egdanielSkia Commit-Bot
authored andcommitted
Add api on GrContext to update the data of GrBackendTextures.
Change-Id: I680f12bf58fc7b66a6b2f3fa4c4723ae84d3f949 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288555 Reviewed-by: Brian Salomon <[email protected]> Commit-Queue: Greg Daniel <[email protected]>
1 parent 2887d35 commit ac09f7c

File tree

4 files changed

+171
-29
lines changed

4 files changed

+171
-29
lines changed

RELEASE_NOTES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ This file includes a list of high level updates for each milestone release.
66

77
Milestone 84
88

9+
* Add api on GrContext, updateBackendTexture that will upload new data to a
10+
GrBackendTexture.
11+
https://review.skia.org/288555
12+
913
* GrContext::createBackendTexture functions that initialize the texture no longer
1014
guarantee that all the data has been uploaded and the gpu is done with the texture.
1115
Instead the client can assume the upload work has been submitted to the gpu and they

include/gpu/GrContext.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,42 @@ class SK_API GrContext : public GrRecordingContext {
546546
finishedContext);
547547
}
548548

549+
/**
550+
* If possible, updates a backend texture to be filled to a particular color. The client should
551+
* check the return value to see if the update was successful. The client can pass in a
552+
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
553+
* deleted. The client can assume the upload work has been submitted to the gpu. The
554+
* finishedProc will always get called even if we failed to update the GrBackendTexture.
555+
* For the Vulkan backend after a successful update the layout of the created VkImage will be:
556+
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
557+
*/
558+
bool updateBackendTexture(const GrBackendTexture&,
559+
const SkColor4f& color,
560+
GrGpuFinishedProc finishedProc,
561+
GrGpuFinishedContext finishedContext);
562+
563+
/**
564+
* If possible, updates a backend texture filled with the provided pixmap data. The client
565+
* should check the return value to see if the update was successful. The client can pass in a
566+
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
567+
* deleted. The client can assume the upload work has been submitted to the gpu. The
568+
* finishedProc will always get called even if we failed to create the GrBackendTexture.
569+
* The backend texture must be compatible with the provided pixmap(s). Compatible, in this case,
570+
* means that the backend format is compatible with the base pixmap's colortype.
571+
* If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
572+
* In the mipmapped case all the colortypes of the provided pixmaps must be the same.
573+
* Additionally, all the miplevels must be sized correctly (please see
574+
* SkMipMap::ComputeLevelSize and ComputeLevelCount).
575+
* Note: the pixmap's alphatypes and colorspaces are ignored.
576+
* For the Vulkan backend after a successful update the layout of the created VkImage will be:
577+
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
578+
*/
579+
bool updateBackendTexture(const GrBackendTexture&,
580+
const SkPixmap srcData[],
581+
int numLevels,
582+
GrGpuFinishedProc finishedProc,
583+
GrGpuFinishedContext finishedContext);
584+
549585
/**
550586
* Retrieve the GrBackendFormat for a given SkImage::CompressionType. This is
551587
* guaranteed to match the backend format used by the following

src/gpu/GrContext.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,58 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n
623623
finishedContext, &data);
624624
}
625625

626+
bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
627+
const SkColor4f& color,
628+
GrGpuFinishedProc finishedProc,
629+
GrGpuFinishedContext finishedContext) {
630+
if (!this->asDirectContext()) {
631+
finishedProc(finishedContext);
632+
return false;
633+
}
634+
635+
if (this->abandoned()) {
636+
finishedProc(finishedContext);
637+
return false;
638+
}
639+
640+
GrGpu::BackendTextureData data(color);
641+
return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data);
642+
}
643+
644+
bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
645+
const SkPixmap srcData[],
646+
int numLevels,
647+
GrGpuFinishedProc finishedProc,
648+
GrGpuFinishedContext finishedContext) {
649+
if (!this->asDirectContext()) {
650+
finishedProc(finishedContext);
651+
return false;
652+
}
653+
654+
if (this->abandoned()) {
655+
finishedProc(finishedContext);
656+
return false;
657+
}
658+
659+
if (!srcData || numLevels <= 0) {
660+
finishedProc(finishedContext);
661+
return false;
662+
}
663+
664+
int numExpectedLevels = 1;
665+
if (backendTexture.hasMipMaps()) {
666+
numExpectedLevels = SkMipMap::ComputeLevelCount(backendTexture.width(),
667+
backendTexture.height()) + 1;
668+
}
669+
if (numLevels != numExpectedLevels) {
670+
finishedProc(finishedContext);
671+
return false;
672+
}
673+
674+
GrGpu::BackendTextureData data(srcData);
675+
return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data);
676+
}
677+
626678
//////////////////////////////////////////////////////////////////////////////
627679

628680
GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height,

tests/BackendAllocationTest.cpp

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828
#include "src/gpu/mtl/GrMtlCppUtil.h"
2929
#endif
3030

31-
static void delete_backend_texture(GrContext* context, const GrBackendTexture& backendTexture,
32-
bool* finishedCreate) {
31+
static void wait_on_backend_work_to_finish(GrContext* context, bool* finishedCreate) {
3332
while (finishedCreate && !(*finishedCreate)) {
3433
context->checkAsyncWorkCompletion();
3534
}
@@ -39,9 +38,18 @@ static void delete_backend_texture(GrContext* context, const GrBackendTexture& b
3938
// Reset it here so that it can be use to signal a future backend texture's creation
4039
*finishedCreate = false;
4140
}
41+
}
42+
43+
static void delete_backend_texture(GrContext* context, const GrBackendTexture& backendTexture,
44+
bool* finishedCreate) {
45+
wait_on_backend_work_to_finish(context, finishedCreate);
4246
context->deleteBackendTexture(backendTexture);
4347
}
4448

49+
static void mark_signaled(void* context) {
50+
*(bool*)context = true;
51+
}
52+
4553
// Test wrapping of GrBackendObjects in SkSurfaces and SkImages (non-static since used in Mtl test)
4654
void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
4755
std::function<GrBackendTexture (GrContext*,
@@ -313,16 +321,35 @@ void test_color_init(GrContext* context, skiatest::Reporter* reporter,
313321
return;
314322
}
315323

316-
if (mipMapped == GrMipMapped::kYes) {
317-
SkColor4f expectedColor = get_expected_color(color, skColorType);
318-
SkColor4f expectedColors[6] = { expectedColor, expectedColor, expectedColor,
319-
expectedColor, expectedColor, expectedColor };
320-
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "colorinit");
321-
}
324+
auto checkBackendTexture = [&](const SkColor4f& testColor) {
325+
if (mipMapped == GrMipMapped::kYes) {
326+
SkColor4f expectedColor = get_expected_color(testColor, skColorType);
327+
SkColor4f expectedColors[6] = {expectedColor, expectedColor, expectedColor,
328+
expectedColor, expectedColor, expectedColor};
329+
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "colorinit");
330+
}
331+
332+
// The last step in this test will dirty the mipmaps so do it last
333+
check_base_readbacks(context, backendTex, skColorType, renderable, testColor, reporter,
334+
"colorinit");
335+
};
336+
337+
checkBackendTexture(color);
338+
339+
// Make sure the initial create work has finished so we can test the update independently.
340+
wait_on_backend_work_to_finish(context, finishedBECreate);
341+
342+
SkColor4f newColor = {color.fB , color.fR, color.fG, color.fA };
343+
344+
// Reupload the new data and make sure everything still works. We test with an SkColorType so
345+
// we may actually swizzle the input during the create path. The update does not do any swizzle
346+
// of the passed in color. So we manually do it here so we get the same expected results.
347+
SkColor4f swizzledColor = context->priv().caps()->getWriteSwizzle(
348+
backendTex.getBackendFormat(), grColorType).applyTo(newColor);
349+
context->updateBackendTexture(backendTex, swizzledColor, mark_signaled, finishedBECreate);
350+
351+
checkBackendTexture(newColor);
322352

323-
// The last step in this test will dirty the mipmaps so do it last
324-
check_base_readbacks(context, backendTex, skColorType, renderable, color,
325-
reporter, "colorinit");
326353
delete_backend_texture(context, backendTex, finishedBECreate);
327354
}
328355

@@ -461,22 +488,49 @@ static void test_pixmap_init(GrContext* context, skiatest::Reporter* reporter,
461488
return;
462489
}
463490

464-
if (mipMapped == GrMipMapped::kYes) {
465-
SkColor4f expectedColors[6] = {
466-
get_expected_color(colors[0], skColorType),
467-
get_expected_color(colors[1], skColorType),
468-
get_expected_color(colors[2], skColorType),
469-
get_expected_color(colors[3], skColorType),
470-
get_expected_color(colors[4], skColorType),
471-
get_expected_color(colors[5], skColorType),
472-
};
473-
474-
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "pixmap");
491+
auto checkBackendTexture = [&](SkColor4f colors[6]) {
492+
if (mipMapped == GrMipMapped::kYes) {
493+
SkColor4f expectedColors[6] = {
494+
get_expected_color(colors[0], skColorType),
495+
get_expected_color(colors[1], skColorType),
496+
get_expected_color(colors[2], skColorType),
497+
get_expected_color(colors[3], skColorType),
498+
get_expected_color(colors[4], skColorType),
499+
get_expected_color(colors[5], skColorType),
500+
};
501+
502+
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "pixmap");
503+
}
504+
505+
// The last step in this test will dirty the mipmaps so do it last
506+
check_base_readbacks(context, backendTex, skColorType, renderable, colors[0], reporter,
507+
"pixmap");
508+
};
509+
510+
checkBackendTexture(colors);
511+
512+
// Make sure the initial create work has finished so we can test the update independently.
513+
wait_on_backend_work_to_finish(context, finishedBECreate);
514+
515+
SkColor4f colorsNew[6] = {
516+
{1.0f, 1.0f, 0.0f, 0.2f}, // Y
517+
{1.0f, 0.0f, 0.0f, 1.0f}, // R
518+
{0.0f, 1.0f, 0.0f, 0.9f}, // G
519+
{0.0f, 0.0f, 1.0f, 0.7f}, // B
520+
{0.0f, 1.0f, 1.0f, 0.5f}, // C
521+
{1.0f, 0.0f, 1.0f, 0.3f}, // M
522+
};
523+
make_pixmaps(skColorType, mipMapped, colorsNew, pixmapMem);
524+
for (int i = 0; i < numMipLevels; ++i) {
525+
pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
475526
}
476527

477-
// The last step in this test will dirty the mipmaps so do it last
478-
check_base_readbacks(context, backendTex, skColorType, renderable, colors[0],
479-
reporter, "pixmap");
528+
// Upload new data and make sure everything still works
529+
context->updateBackendTexture(backendTex, pixmaps, numMipLevels, mark_signaled,
530+
finishedBECreate);
531+
532+
checkBackendTexture(colorsNew);
533+
480534
delete_backend_texture(context, backendTex, finishedBECreate);
481535
}
482536

@@ -509,10 +563,6 @@ void check_vk_layout(const GrBackendTexture& backendTex, VkLayout layout) {
509563
#endif
510564
}
511565

512-
static void mark_signaled(void* context) {
513-
*(bool*)context = true;
514-
}
515-
516566
///////////////////////////////////////////////////////////////////////////////
517567
// This test is a bit different from the others in this file. It is mainly checking that, for any
518568
// SkSurface we can create in Ganesh, we can also create a backend texture that is compatible with

0 commit comments

Comments
 (0)