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; |