Add SkImage::NewTextureFromPixmap
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1776913003 Review URL: https://codereview.chromium.org/1776913003
This commit is contained in:
parent
7d825f8d5c
commit
045afea979
@ -145,6 +145,8 @@ public:
|
||||
static SkImage* NewFromPicture(const SkPicture*, const SkISize& dimensions,
|
||||
const SkMatrix*, const SkPaint*);
|
||||
|
||||
static SkImage* NewTextureFromPixmap(GrContext*, const SkPixmap&, SkBudgeted budgeted);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int width() const { return fWidth; }
|
||||
|
100
src/gpu/SkGr.cpp
100
src/gpu/SkGr.cpp
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include "SkGr.h"
|
||||
#include "SkGrPriv.h"
|
||||
|
||||
#include "GrCaps.h"
|
||||
#include "GrContext.h"
|
||||
@ -121,16 +122,10 @@ GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
|
||||
* Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
|
||||
* as the colortable.count says it is.
|
||||
*/
|
||||
static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
|
||||
SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
|
||||
static void build_index8_data(void* buffer, const SkPixmap& pixmap) {
|
||||
SkASSERT(kIndex_8_SkColorType == pixmap.colorType());
|
||||
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
if (!bitmap.readyToDraw()) {
|
||||
SkDEBUGFAIL("bitmap not ready to draw!");
|
||||
return;
|
||||
}
|
||||
|
||||
SkColorTable* ctable = bitmap.getColorTable();
|
||||
const SkColorTable* ctable = pixmap.ctable();
|
||||
char* dst = (char*)buffer;
|
||||
|
||||
const int count = ctable->count();
|
||||
@ -152,14 +147,14 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
|
||||
// always skip a full 256 number of entries, even if we memcpy'd fewer
|
||||
dst += 256 * sizeof(GrColor);
|
||||
|
||||
if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
|
||||
memcpy(dst, bitmap.getPixels(), bitmap.getSize());
|
||||
if ((unsigned)pixmap.width() == pixmap.rowBytes()) {
|
||||
memcpy(dst, pixmap.addr(), pixmap.getSafeSize());
|
||||
} else {
|
||||
// need to trim off the extra bytes per row
|
||||
size_t width = bitmap.width();
|
||||
size_t rowBytes = bitmap.rowBytes();
|
||||
const char* src = (const char*)bitmap.getPixels();
|
||||
for (int y = 0; y < bitmap.height(); y++) {
|
||||
size_t width = pixmap.width();
|
||||
size_t rowBytes = pixmap.rowBytes();
|
||||
const uint8_t* src = pixmap.addr8();
|
||||
for (int y = 0; y < pixmap.height(); y++) {
|
||||
memcpy(dst, src, width);
|
||||
src += rowBytes;
|
||||
dst += width;
|
||||
@ -218,58 +213,61 @@ static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfac
|
||||
return ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes, startOfTexData, 0);
|
||||
}
|
||||
|
||||
GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
|
||||
SkASSERT(!bmp.getTexture());
|
||||
GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bitmap) {
|
||||
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
|
||||
if (GrTexture *texture = load_etc1_texture(ctx, bitmap, desc)) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
if (GrTexture* texture = create_texture_from_yuv(ctx, bitmap, desc)) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
if (!bitmap.readyToDraw()) {
|
||||
return nullptr;
|
||||
}
|
||||
SkPixmap pixmap;
|
||||
if (!bitmap.peekPixels(&pixmap)) {
|
||||
return nullptr;
|
||||
}
|
||||
return GrUploadPixmapToTexture(ctx, pixmap);
|
||||
}
|
||||
|
||||
GrTexture* GrUploadPixmapToTexture(GrContext* ctx, const SkPixmap& pixmap) {
|
||||
const SkPixmap* pmap = &pixmap;
|
||||
SkPixmap tmpPixmap;
|
||||
SkBitmap tmpBitmap;
|
||||
const SkBitmap* bitmap = &bmp;
|
||||
|
||||
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info());
|
||||
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info());
|
||||
const GrCaps* caps = ctx->caps();
|
||||
|
||||
if (kIndex_8_SkColorType == bitmap->colorType()) {
|
||||
if (kIndex_8_SkColorType == pixmap.colorType()) {
|
||||
if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
|
||||
size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
|
||||
bitmap->width(), bitmap->height());
|
||||
pixmap.width(), pixmap.height());
|
||||
SkAutoMalloc storage(imageSize);
|
||||
build_index8_data(storage.get(), bmp);
|
||||
build_index8_data(storage.get(), pixmap);
|
||||
|
||||
// our compressed data will be trimmed, so pass width() for its
|
||||
// "rowBytes", since they are the same now.
|
||||
return ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes, storage.get(),
|
||||
bitmap->width());
|
||||
pixmap.width());
|
||||
} else {
|
||||
bmp.copyTo(&tmpBitmap, kN32_SkColorType);
|
||||
// now bitmap points to our temp, which has been promoted to 32bits
|
||||
bitmap = &tmpBitmap;
|
||||
desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
|
||||
}
|
||||
} else if (!bitmap->readyToDraw()) {
|
||||
// If the bitmap had compressed data and was then uncompressed, it'll still return
|
||||
// compressed data on 'refEncodedData' and upload it. Probably not good, since if
|
||||
// the bitmap has available pixels, then they might not be what the decompressed
|
||||
// data is.
|
||||
|
||||
// Really?? We aren't doing this with YUV.
|
||||
|
||||
GrTexture *texture = load_etc1_texture(ctx, *bitmap, desc);
|
||||
if (texture) {
|
||||
return texture;
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
|
||||
tmpBitmap.allocPixels(info);
|
||||
if (!pixmap.readPixels(info, tmpBitmap.getPixels(), tmpBitmap.rowBytes())) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!tmpBitmap.peekPixels(&tmpPixmap)) {
|
||||
return nullptr;
|
||||
}
|
||||
pmap = &tmpPixmap;
|
||||
}
|
||||
}
|
||||
|
||||
GrTexture *texture = create_texture_from_yuv(ctx, *bitmap, desc);
|
||||
if (texture) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(*bitmap);
|
||||
if (!bitmap->readyToDraw()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes, bitmap->getPixels(),
|
||||
bitmap->rowBytes());
|
||||
return ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes, pmap->addr(),
|
||||
pmap->rowBytes());
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,6 +121,11 @@ GrTexture* GrUploadBitmapToTexture(GrContext*, const SkBitmap&);
|
||||
|
||||
GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext*, const SkBitmap&);
|
||||
|
||||
/**
|
||||
* Creates a new texture for the pixmap.
|
||||
*/
|
||||
GrTexture* GrUploadPixmapToTexture(GrContext*, const SkPixmap&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GR_STATIC_ASSERT((int)kZero_GrBlendCoeff == (int)SkXfermode::kZero_Coeff);
|
||||
|
@ -343,6 +343,10 @@ bool SkImage::isLazyGenerated() const {
|
||||
|
||||
#if !SK_SUPPORT_GPU
|
||||
|
||||
SkImage* SkImage::NewTextureFromPixmap(GrContext*, const SkPixmap&, SkBudgeted budgeted) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
|
||||
TextureReleaseProc, ReleaseContext) {
|
||||
return nullptr;
|
||||
|
@ -310,6 +310,19 @@ SkImage* SkImage::newTextureImage(GrContext *context) const {
|
||||
return create_image_from_maker(&maker, at, this->uniqueID());
|
||||
}
|
||||
|
||||
SkImage* SkImage::NewTextureFromPixmap(GrContext* ctx, const SkPixmap& pixmap,
|
||||
SkBudgeted budgeted) {
|
||||
if (!ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
SkAutoTUnref<GrTexture> texture(GrUploadPixmapToTexture(ctx, pixmap));
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SkImage_Gpu(texture->width(), texture->height(), kNeedNewImageUniqueID,
|
||||
pixmap.alphaType(), texture, budgeted);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include "DMGpuSupport.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
@ -67,6 +68,31 @@ static SkImage* create_image() {
|
||||
draw_image_test_pattern(surface->getCanvas());
|
||||
return surface->newImageSnapshot();
|
||||
}
|
||||
static SkImage* create_image_565() {
|
||||
const SkImageInfo info = SkImageInfo::Make(20, 20, kRGB_565_SkColorType, kOpaque_SkAlphaType);
|
||||
SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
|
||||
draw_image_test_pattern(surface->getCanvas());
|
||||
return surface->newImageSnapshot();
|
||||
}
|
||||
#if 0
|
||||
static SkImage* create_image_ct() {
|
||||
SkPMColor colors[] = {
|
||||
SkPreMultiplyARGB(0xFF, 0xFF, 0xFF, 0x00),
|
||||
SkPreMultiplyARGB(0x80, 0x00, 0xA0, 0xFF),
|
||||
SkPreMultiplyARGB(0xFF, 0xBB, 0x00, 0xBB)
|
||||
};
|
||||
SkAutoTUnref<SkColorTable> colorTable(new SkColorTable(colors, SK_ARRAY_COUNT(colors)));
|
||||
uint8_t data[] = {
|
||||
0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 1, 2, 1, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
SkImageInfo info = SkImageInfo::Make(5, 5, kIndex_8_SkColorType, kPremul_SkAlphaType);
|
||||
return SkImage::NewRasterCopy(info, data, 5, colorTable);
|
||||
}
|
||||
#endif
|
||||
static SkData* create_image_data(SkImageInfo* info) {
|
||||
*info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
|
||||
const size_t rowBytes = info->minRowBytes();
|
||||
@ -737,4 +763,72 @@ DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_NewFromTexture, reporter, context) {
|
||||
refImg.reset(nullptr); // force a release of the image
|
||||
REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
|
||||
}
|
||||
|
||||
static void check_images_same(skiatest::Reporter* reporter, const SkImage* a, const SkImage* b) {
|
||||
if (a->width() != b->width() || a->height() != b->height()) {
|
||||
ERRORF(reporter, "Images must have the same size");
|
||||
return;
|
||||
}
|
||||
if (a->isOpaque() != b->isOpaque()) {
|
||||
ERRORF(reporter, "Images must have the same opaquness");
|
||||
return;
|
||||
}
|
||||
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height());
|
||||
SkAutoPixmapStorage apm;
|
||||
SkAutoPixmapStorage bpm;
|
||||
|
||||
apm.alloc(info);
|
||||
bpm.alloc(info);
|
||||
|
||||
if (!a->readPixels(apm, 0, 0)) {
|
||||
ERRORF(reporter, "Could not read image a's pixels");
|
||||
return;
|
||||
}
|
||||
if (!b->readPixels(bpm, 0, 0)) {
|
||||
ERRORF(reporter, "Could not read image b's pixels");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto y = 0; y < info.height(); ++y) {
|
||||
for (auto x = 0; x < info.width(); ++x) {
|
||||
uint32_t pixelA = *apm.addr32(x, y);
|
||||
uint32_t pixelB = *bpm.addr32(x, y);
|
||||
if (pixelA != pixelB) {
|
||||
ERRORF(reporter, "Expected image pixels to be the same. At %d,%d 0x%08x != 0x%08x",
|
||||
x, y, pixelA, pixelB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(NewTextureFromPixmap, reporter, context) {
|
||||
for (auto create : {&create_image,
|
||||
&create_image_565
|
||||
#if 0 // peekPixels on color table images is currently broken.
|
||||
, &create_image_ct
|
||||
#endif
|
||||
}) {
|
||||
SkAutoTUnref<SkImage> image((*create)());
|
||||
if (!image) {
|
||||
ERRORF(reporter, "Could not create image");
|
||||
return;
|
||||
}
|
||||
|
||||
SkPixmap pixmap;
|
||||
if (!image->peekPixels(&pixmap)) {
|
||||
ERRORF(reporter, "peek failed");
|
||||
} else {
|
||||
SkAutoTUnref<SkImage> texImage(SkImage::NewTextureFromPixmap(context, pixmap,
|
||||
SkBudgeted::kNo));
|
||||
if (!texImage) {
|
||||
ERRORF(reporter, "NewTextureFromPixmap failed.");
|
||||
} else {
|
||||
check_images_same(reporter, image, texImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user