Chromium Code Reviews| Index: src/image/SkImage_Gpu.cpp |
| diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp |
| index 57ee33957bf9cd6625045c9f623849e8d7b14e86..04e573753207e7ab44e1015385096914073326de 100644 |
| --- a/src/image/SkImage_Gpu.cpp |
| +++ b/src/image/SkImage_Gpu.cpp |
| @@ -310,6 +310,174 @@ 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); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +class SkImage::DeferredTextureImage { |
| +public: |
| + SkImage* newImage(GrContext* context, SkBudgeted) const; |
| + |
| +private: |
| + uint32_t fContextUniqueID; |
| + uint32_t fImageUniqueID; |
| + struct Data { |
| + SkImageInfo fInfo; |
| + void* fPixelData; |
| + size_t fRowBytes; |
| + int fColorTableCnt; |
| + uint32_t* fColorTableData; |
| + }; |
| + Data fData; |
| + |
| + friend class SkImage; |
| + static bool GetSizeOrInit(const SkImage* image, const GrContextThreadSafeProxy& proxy, |
|
robertphillips
2016/03/08 18:43:10
line these up ?
bsalomon
2016/03/08 19:49:32
Done.
|
| + void* inBuffer, size_t inSize, size_t* outSize, |
| + DeferredTextureImage** outDeferredTextureImage); |
| + |
| +}; |
| + |
| +bool SkImage::DeferredTextureImage::GetSizeOrInit(const SkImage* image, |
| + const GrContextThreadSafeProxy& proxy, |
| + void* inBuffer, size_t inSize, size_t* outSize, |
| + SkImage::DeferredTextureImage** outDeferredTextureImage) { |
| + // This function has two modes, (1) querying for the size of the SkImageTextureData, and (2) |
| + // creating the SkImageTextureData in a client buffer. |
| + if (!inBuffer) { |
| + // Mode 1. |
| + if (inSize) { |
| + return false; |
| + } |
| + if (outDeferredTextureImage) { |
| + return false; |
| + } |
| + } else { |
| + // Mode 2. |
| + if (outSize) { |
| + return false; |
| + } |
| + if (!outDeferredTextureImage) { |
| + return false; |
| + } |
| + } |
| + SkAutoPixmapStorage pixmap; |
| + SkImageInfo info; |
| + size_t pixelSize = 0; |
| + size_t ctSize = 0; |
| + int ctCount = 0; |
| + if (image->peekPixels(&pixmap)) { |
| + info = pixmap.info(); |
| + pixelSize = SkAlign8(pixmap.getSafeSize()); |
| + if (pixmap.ctable()) { |
| + ctCount = pixmap.ctable()->count(); |
| + ctSize = SkAlign8(pixmap.ctable()->count() * 4); |
| + } |
| + } else { |
| + // Here we're just using presence of data to know whether there is a codec behind the image. |
| + // In the future we will access the cacherator and get the exact data that we want to (e.g. |
| + // yuv planes) upload. |
| + SkAutoTUnref<SkData> data(image->refEncoded()); |
| + if (!data) { |
|
robertphillips
2016/03/08 18:43:10
too far over ?
bsalomon
2016/03/08 19:49:32
Done.
|
| + return false; |
| + } |
| + SkAlphaType at = image->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; |
| + info = SkImageInfo::MakeN32(image->width(), image->height(), at); |
| + pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr)); |
| + if (inBuffer) { |
| + pixmap.alloc(info); |
| + if (!image->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) { |
| + return false; |
| + } |
| + SkASSERT(!pixmap.ctable()); |
| + } |
| + } |
| + size_t size = 0; |
|
robertphillips
2016/03/08 18:43:10
is this supposed to be dtiSize ?
bsalomon
2016/03/08 19:49:32
Done.
|
| + size_t itdSize = SkAlign8(sizeof(DeferredTextureImage)); |
| + size += itdSize; |
| + size_t pixelOffset = size; |
| + size += pixelSize; |
| + size_t ctOffset = size; |
| + size += ctSize; |
| + if (!inBuffer) { |
| + *outSize = size; |
| + return true; |
| + } else if (inSize < size) { |
| + return false; |
| + } |
| + intptr_t allocation = reinterpret_cast<intptr_t>(inBuffer); |
|
robertphillips
2016/03/08 18:43:10
itd -> dti ?
bsalomon
2016/03/08 19:49:32
Done.
|
| + void* itd = reinterpret_cast<void*>(allocation); |
| + void* pixels = reinterpret_cast<void*>(allocation + pixelOffset); |
| + SkPMColor* ct = nullptr; |
| + if (ctSize) { |
| + ct = reinterpret_cast<SkPMColor*>(allocation + ctOffset); |
| + } |
| + |
| + memcpy(pixels, pixmap.addr(), pixmap.getSafeSize()); |
| + if (ctSize) { |
| + memcpy(ct, pixmap.ctable()->readColors(), ctSize); |
| + } |
| + |
| + SkASSERT(info == pixmap.info()); |
| + size_t rowBytes = pixmap.rowBytes(); |
| + (*outDeferredTextureImage) = new (itd) DeferredTextureImage(); |
| + (*outDeferredTextureImage)->fContextUniqueID = proxy.fContextUniqueID; |
| + (*outDeferredTextureImage)->fImageUniqueID = image->uniqueID(); |
| + (*outDeferredTextureImage)->fData.fInfo = info; |
| + (*outDeferredTextureImage)->fData.fPixelData = pixels; |
| + (*outDeferredTextureImage)->fData.fRowBytes = rowBytes; |
| + (*outDeferredTextureImage)->fData.fColorTableCnt = ctCount; |
| + (*outDeferredTextureImage)->fData.fColorTableData = ct; |
| + return true; |
| +} |
| + |
| +size_t SkImage::getDeferredTextureImageSize(const GrContextThreadSafeProxy& proxy, |
| + const DeferredTextureImageUsageParams[], |
| + int paramCnt) const { |
| + size_t size; |
| + if (DeferredTextureImage::GetSizeOrInit(this, proxy, nullptr, 0, &size, nullptr)) { |
| + return size; |
| + } |
| + return 0; |
| +} |
| + |
| +const SkImage::DeferredTextureImage* SkImage::createDeferredTextureImageInClientStorage( |
| + const GrContextThreadSafeProxy& proxy, |
| + const DeferredTextureImageUsageParams[], int paramCnt, |
| + void* buffer, size_t bufferSize) const { |
| + DeferredTextureImage* deferredTextureImage; |
| + if (DeferredTextureImage::GetSizeOrInit(this, proxy, buffer, bufferSize, nullptr, |
| + &deferredTextureImage)) { |
| + return deferredTextureImage; |
| + } |
| + return nullptr; |
| +} |
| + |
| +SkImage* SkImage::NewFromDeferredTextureImage(GrContext* context, const DeferredTextureImage& dti, |
| + SkBudgeted budgeted) { |
| + if (!context || context->uniqueID() != dti.fContextUniqueID) { |
| + return nullptr; |
| + } |
| + SkAutoTUnref<SkColorTable> colorTable; |
| + if (dti.fData.fColorTableCnt) { |
| + SkASSERT(dti.fData.fColorTableData); |
| + colorTable.reset(new SkColorTable(dti.fData.fColorTableData, dti.fData.fColorTableCnt)); |
| + } |
| + SkPixmap pixmap; |
| + pixmap.reset(dti.fData.fInfo, dti.fData.fPixelData, dti.fData.fRowBytes, colorTable.get()); |
| + return SkImage::NewTextureFromPixmap(context, pixmap, budgeted); |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) { |