Index: src/gpu/SkGr.cpp |
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp |
index c4e2c1f93fd87b128a27206a3f0256f40fcc4456..9882681ddadbeec8c8609426c16511b5be370755 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 }; |
+ size_t 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) { |
robertphillips
2014/07/10 18:27:38
Shouldn't all the rowBytes be the same (and equal
sugoi1
2014/07/10 19:59:06
No, YUV components are stored sequentially, not in
|
+ 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]; |
robertphillips
2014/07/10 18:27:38
Shouldn't this be sizes[0] + sizes[1] ?
robertphillips
2014/07/10 18:28:43
Forget this comment - I overlooked that you use pl
|
+ planes[2] = (uint8_t*)planes[1] + sizes[1]; |
+ |
+ // Get the YUV planes |
+ if ((NULL == planes[0]) || !pixelRef->getYUV8Planes(yuvSizes, planes, rowBytes)) { |
+ 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; |
robertphillips
2014/07/10 18:27:38
Replace "GrTexture* tex =" with "yuvTextures[i].re
sugoi1
2014/07/10 19:59:06
Sure, doesn't hurt.
|
+ GrTexture* tex = ctx->createUncachedTexture(yuvDesc, planes[i], rowBytes[i]); |
+ 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); |
+ 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; |