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) { |