Index: src/gpu/SkGr.cpp |
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp |
index c4e2c1f93fd87b128a27206a3f0256f40fcc4456..63d1bb30e16666ee10aca5db3a1bf6899c46c1a2 100644 |
--- a/src/gpu/SkGr.cpp |
+++ b/src/gpu/SkGr.cpp |
@@ -15,6 +15,7 @@ |
#include "GrGpu.h" |
#include "effects/GrDitherEffect.h" |
#include "GrDrawTargetCaps.h" |
+#include "effects/GrYUVtoRGBEffect.h" |
#ifndef SK_IGNORE_ETC1_SUPPORT |
# include "ktx.h" |
@@ -193,6 +194,79 @@ static GrTexture *load_etc1_texture(GrContext* ctx, |
} |
#endif // SK_IGNORE_ETC1_SUPPORT |
+static GrTexture *load_yuv_texture(GrContext* ctx, const GrTextureParams* params, |
+ const SkBitmap& bm, const GrTextureDesc& desc) { |
+ GrTexture* result = NULL; |
+ |
+ SkPixelRef* pixelRef = bm.pixelRef(); |
+ SkISize yuvSizes[3]; |
+ void* planes[3] = { NULL, NULL, NULL }; |
+ int rowBytes[3] = { 0, 0, 0 }; |
+ if ((NULL == pixelRef) || !pixelRef->getYUV8Planes(yuvSizes, planes, rowBytes)) { |
+ return NULL; |
+ } |
+ |
+ // Allocate the memory for YUV |
+ size_t totalSize = 0; |
+ size_t sizes[3]; |
+ for (int i = 0; i < 3; ++i) { |
+ rowBytes[i] = yuvSizes[i].fWidth; |
+ totalSize += sizes[i] = rowBytes[i] * yuvSizes[i].fHeight; |
+ } |
+ SkAutoMalloc storage(totalSize); |
+ planes[0] = storage.get(); |
+ planes[1] = (uint8_t*)planes[0] + sizes[0]; |
+ planes[2] = (uint8_t*)planes[1] + sizes[1]; |
+ |
+ // Get the YUV planes |
+ if ((NULL == planes[0]) || !pixelRef->getYUV8Planes(yuvSizes, planes, rowBytes)) { |
reed1
2014/07/10 17:15:15
I don't think SkAutoMalloc can ever fail, can it?
sugoi1
2014/07/10 17:54:24
I don't know. What happens if we're out of memory?
|
+ return NULL; |
+ } |
+ |
+ GrTextureDesc yuvDesc; |
+ yuvDesc.fConfig = kAlpha_8_GrPixelConfig; |
+ SkAutoTUnref<GrTexture> yuvTextures[3]; |
+ for (int i = 0; i < 3; ++i) { |
+ yuvDesc.fWidth = yuvSizes[i].fWidth; |
+ yuvDesc.fHeight = yuvSizes[i].fHeight; |
+ GrTexture* tex = ctx->createUncachedTexture(yuvDesc, planes[i], rowBytes[i]); |
bsalomon
2014/07/10 18:29:39
We should probably use scratch textures here. We'd
sugoi1
2014/07/10 19:59:06
Done.
|
+ if (NULL == tex) { |
+ return NULL; |
+ } |
+ yuvTextures[i].reset(tex); |
+ } |
+ |
+ GrTextureDesc rtDesc = desc; |
+ rtDesc.fFlags = rtDesc.fFlags | |
+ kRenderTarget_GrTextureFlagBit | |
+ kNoStencil_GrTextureFlagBit; |
+ |
+ // This texture is likely to be used again so leave it in the cache |
+ GrCacheID cacheID; |
+ generate_bitmap_cache_id(bm, &cacheID); |
+ |
+ GrResourceKey key; |
+ result = ctx->createTexture(params, rtDesc, cacheID, NULL, 0, &key); |
+ GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL; |
+ if (NULL != renderTarget) { |
+ add_genID_listener(key, bm.pixelRef()); |
+ SkAutoTUnref<GrEffect> yuvToRgbEffect(GrYUVtoRGBEffect::Create( |
+ yuvTextures[0].get(), yuvTextures[1].get(), yuvTextures[2].get())); |
+ GrPaint paint; |
+ paint.addColorEffect(yuvToRgbEffect); |
+ SkRect r = SkRect::MakeWH(yuvSizes[0].fWidth, yuvSizes[0].fHeight); |
+ GrContext::AutoRenderTarget autoRT(ctx, renderTarget); |
+ GrContext::AutoMatrix am; |
+ am.setIdentity(ctx); |
+ GrContext::AutoClip ac(ctx, r); |
bsalomon
2014/07/10 18:29:39
Maybe ac(ctx, GrContext::AutoClip::kWideOpen_Initi
sugoi1
2014/07/10 19:59:06
Will that work if I'm rendering a JPEG while rende
sugoi1
2014/07/11 18:46:15
Done. Seems to work properly in all cases I've tes
|
+ ctx->drawRect(paint, r); |
+ } else { |
+ SkSafeSetNull(result); |
+ } |
+ |
+ return result; |
+} |
+ |
static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, |
bool cache, |
const GrTextureParams* params, |
@@ -264,6 +338,12 @@ static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, |
} |
#endif // SK_IGNORE_ETC1_SUPPORT |
+ else { |
+ GrTexture *texture = load_yuv_texture(ctx, params, *bitmap, desc); |
+ if (NULL != texture) { |
+ return texture; |
+ } |
+ } |
SkAutoLockPixels alp(*bitmap); |
if (!bitmap->readyToDraw()) { |
return NULL; |