• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrContext.h"
9 #include "GrDrawContext.h"
10 #include "GrYUVProvider.h"
11 #include "effects/GrYUVEffect.h"
12 
13 #include "SkCachedData.h"
14 #include "SkRefCnt.h"
15 #include "SkResourceCache.h"
16 #include "SkYUVPlanesCache.h"
17 
18 namespace {
19 /**
20  *  Helper class to manage the resources used for storing the YUV planar data. Depending on the
21  *  useCache option, we may find (and lock) the data in our ResourceCache, or we may have allocated
22  *  it in scratch storage.
23  */
24 class YUVScoper {
25 public:
26     bool init(GrYUVProvider*, SkYUVPlanesCache::Info*, void* planes[3], bool useCache);
27 
28 private:
29     // we only use one or the other of these
30     SkAutoTUnref<SkCachedData>  fCachedData;
31     SkAutoMalloc                fStorage;
32 };
33 }
34 
init(GrYUVProvider * provider,SkYUVPlanesCache::Info * yuvInfo,void * planes[3],bool useCache)35 bool YUVScoper::init(GrYUVProvider* provider, SkYUVPlanesCache::Info* yuvInfo, void* planes[3],
36                      bool useCache) {
37     if (useCache) {
38         fCachedData.reset(SkYUVPlanesCache::FindAndRef(provider->onGetID(), yuvInfo));
39     }
40 
41     if (fCachedData.get()) {
42         planes[0] = (void*)fCachedData->data();
43         planes[1] = (uint8_t*)planes[0] + yuvInfo->fSizeInMemory[0];
44         planes[2] = (uint8_t*)planes[1] + yuvInfo->fSizeInMemory[1];
45     } else {
46         // Fetch yuv plane sizes for memory allocation. Here, width and height can be
47         // rounded up to JPEG block size and be larger than the image's width and height.
48         if (!provider->onGetYUVSizes(yuvInfo->fSize)) {
49             return false;
50         }
51 
52         // Allocate the memory for YUV
53         size_t totalSize(0);
54         for (int i = 0; i < GrYUVProvider::kPlaneCount; ++i) {
55             yuvInfo->fRowBytes[i] = yuvInfo->fSize[i].fWidth; // we assume snug fit: rb == width
56             yuvInfo->fSizeInMemory[i] = yuvInfo->fRowBytes[i] * yuvInfo->fSize[i].fHeight;
57             totalSize += yuvInfo->fSizeInMemory[i];
58         }
59         if (useCache) {
60             fCachedData.reset(SkResourceCache::NewCachedData(totalSize));
61             planes[0] = fCachedData->writable_data();
62         } else {
63             fStorage.reset(totalSize);
64             planes[0] = fStorage.get();
65         }
66         planes[1] = (uint8_t*)planes[0] + yuvInfo->fSizeInMemory[0];
67         planes[2] = (uint8_t*)planes[1] + yuvInfo->fSizeInMemory[1];
68 
69         // Get the YUV planes and update plane sizes to actual image size
70         if (!provider->onGetYUVPlanes(yuvInfo->fSize, planes, yuvInfo->fRowBytes,
71                                       &yuvInfo->fColorSpace)) {
72             return false;
73         }
74 
75         if (useCache) {
76             // Decoding is done, cache the resulting YUV planes
77             SkYUVPlanesCache::Add(provider->onGetID(), fCachedData, yuvInfo);
78         }
79     }
80     return true;
81 }
82 
refAsTexture(GrContext * ctx,const GrSurfaceDesc & desc,bool useCache)83 GrTexture* GrYUVProvider::refAsTexture(GrContext* ctx, const GrSurfaceDesc& desc, bool useCache) {
84     SkYUVPlanesCache::Info yuvInfo;
85     void* planes[3];
86     YUVScoper scoper;
87     if (!scoper.init(this, &yuvInfo, planes, useCache)) {
88         return nullptr;
89     }
90 
91     GrSurfaceDesc yuvDesc;
92     yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
93     SkAutoTUnref<GrTexture> yuvTextures[3];
94     for (int i = 0; i < 3; ++i) {
95         yuvDesc.fWidth  = yuvInfo.fSize[i].fWidth;
96         yuvDesc.fHeight = yuvInfo.fSize[i].fHeight;
97         // TODO: why do we need this check?
98         bool needsExactTexture = (yuvDesc.fWidth  != yuvInfo.fSize[0].fWidth) ||
99                                  (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight);
100         if (needsExactTexture) {
101             yuvTextures[i].reset(ctx->textureProvider()->createTexture(yuvDesc, SkBudgeted::kYes));
102         } else {
103             yuvTextures[i].reset(ctx->textureProvider()->createApproxTexture(yuvDesc));
104         }
105         if (!yuvTextures[i] ||
106             !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
107                                          yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) {
108                 return nullptr;
109             }
110     }
111 
112     GrSurfaceDesc rtDesc = desc;
113     rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
114 
115     SkAutoTUnref<GrTexture> result(ctx->textureProvider()->createTexture(rtDesc, SkBudgeted::kYes,
116                                                                          nullptr, 0));
117     if (!result) {
118         return nullptr;
119     }
120 
121     GrRenderTarget* renderTarget = result->asRenderTarget();
122     SkASSERT(renderTarget);
123 
124     GrPaint paint;
125     SkAutoTUnref<const GrFragmentProcessor> yuvToRgbProcessor(
126                                         GrYUVEffect::CreateYUVToRGB(yuvTextures[0],
127                                                                     yuvTextures[1],
128                                                                     yuvTextures[2],
129                                                                     yuvInfo.fSize,
130                                                                     yuvInfo.fColorSpace));
131     paint.addColorFragmentProcessor(yuvToRgbProcessor);
132     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
133     const SkRect r = SkRect::MakeIWH(yuvInfo.fSize[0].fWidth, yuvInfo.fSize[0].fHeight);
134 
135     SkAutoTUnref<GrDrawContext> drawContext(ctx->drawContext(renderTarget));
136     if (!drawContext) {
137         return nullptr;
138     }
139 
140     drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), r);
141 
142     return result.detach();
143 }
144 
145