Chromium Code Reviews| Index: src/gpu/SkGr.cpp |
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp |
| index a1b379fe8c83dd562bd22cd793a67fd2e0e772aa..ea53290357a97c9e6bb6291ee6911ef287e6329f 100644 |
| --- a/src/gpu/SkGr.cpp |
| +++ b/src/gpu/SkGr.cpp |
| @@ -9,12 +9,14 @@ |
| #include "SkColorFilter.h" |
| #include "SkConfig8888.h" |
| #include "SkData.h" |
| +#include "SkImageGenerator.h" |
| #include "SkMessageBus.h" |
| #include "SkPixelRef.h" |
| #include "GrResourceCache.h" |
| #include "GrGpu.h" |
| #include "effects/GrDitherEffect.h" |
| #include "GrDrawTargetCaps.h" |
| +#include "effects/GrYUVtoRGBEffect.h" |
| #ifndef SK_IGNORE_ETC1_SUPPORT |
| # include "ktx.h" |
| @@ -193,6 +195,90 @@ 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, GrTextureDesc desc) { |
| + GrTexture* result = NULL; |
| + |
| + SkPixelRef* pixelRef = bm.pixelRef(); |
| + SkImageGenerator* imageGenerator = pixelRef ? pixelRef->getImageGenerator() : NULL; |
| + if (imageGenerator) { |
| + SkISize yuvSizes[3]; |
| + if (imageGenerator->getYUV8Planes(yuvSizes)) { |
| + SkImageGenerator::YUV8Planes planes; |
| + // Set the info based on the Y channel's size |
| + planes.fInfo = SkImageInfo::MakeN32Premul(yuvSizes[0].fWidth, yuvSizes[0].fHeight); |
| + // Allcate the memory for YUV |
| + size_t ySize = yuvSizes[0].fWidth * yuvSizes[0].fHeight; |
| + size_t uSize = yuvSizes[1].fWidth * yuvSizes[1].fHeight; |
| + // size_t vSize = yuvSizes[2].fWidth * yuvSizes[2].fHeight; |
| + size_t yuvSize = 4 * ySize; // FIXME: ySize + uSize + vSize; |
|
sugoi1
2014/07/08 14:42:02
There's still a FIXME here. This allocated memory
|
| + planes.fPixels = (uint8_t*)sk_malloc_flags(yuvSize, 0); |
| + // Get the YUV planes |
| + if ((NULL != planes.fPixels) && |
| + imageGenerator->getYUV8Planes(yuvSizes, &planes)) { |
| + // Put the planes into SkBitmap objects |
| + SkBitmap yBitmap, uBitmap, vBitmap; |
| + SkImageInfo yInfo = SkImageInfo::MakeA8(yuvSizes[0].fWidth, yuvSizes[0].fHeight); |
| + SkImageInfo uInfo = SkImageInfo::MakeA8(yuvSizes[1].fWidth, yuvSizes[1].fHeight); |
| + SkImageInfo vInfo = SkImageInfo::MakeA8(yuvSizes[2].fWidth, yuvSizes[2].fHeight); |
| + if (yBitmap.installPixels(yInfo, planes.fPixels, yInfo.minRowBytes()) && |
| + uBitmap.installPixels(uInfo, planes.fPixels + ySize, uInfo.minRowBytes()) && |
| + vBitmap.installPixels(vInfo, planes.fPixels + ySize + uSize, vInfo.minRowBytes())) { |
| + // Upload bitmaps as textures (don't cache these) |
| + yBitmap.setIsVolatile(true); |
| + uBitmap.setIsVolatile(true); |
| + vBitmap.setIsVolatile(true); |
| + GrTexture* yTexture = GrLockAndRefCachedBitmapTexture(ctx, yBitmap, params); |
| + GrTexture* uTexture = GrLockAndRefCachedBitmapTexture(ctx, uBitmap, params); |
| + GrTexture* vTexture = GrLockAndRefCachedBitmapTexture(ctx, vBitmap, params); |
| + if (yTexture && uTexture && vTexture) { |
| + 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()); |
| + GrEffectRef* yuvToRgbEffect = GrYUVtoRGBEffect::Create(yTexture, uTexture, vTexture); |
| + SkAutoUnref effectRef(yuvToRgbEffect); |
| + 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); |
| + } |
| + } |
| + if (NULL != yTexture) { |
| + GrUnlockAndUnrefCachedBitmapTexture(yTexture); |
| + } |
| + if (NULL != uTexture) { |
| + GrUnlockAndUnrefCachedBitmapTexture(uTexture); |
| + } |
| + if (NULL != vTexture) { |
| + GrUnlockAndUnrefCachedBitmapTexture(vTexture); |
| + } |
| + } |
| + } |
| + sk_free(planes.fPixels); |
| + } |
| + } |
| + |
| + return result; |
| +} |
| + |
| static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, |
| bool cache, |
| const GrTextureParams* params, |
| @@ -264,6 +350,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); |
|
sugoi1
2014/07/08 14:42:03
The "cache" boolean should probably be used here,
|
| + if (NULL != texture) { |
| + return texture; |
| + } |
| + } |
| SkAutoLockPixels alp(*bitmap); |
| if (!bitmap->readyToDraw()) { |
| return NULL; |