Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / SkGrPixelRef.cpp
1
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9
10
11 #include "SkGrPixelRef.h"
12
13 #include "GrContext.h"
14 #include "GrTexture.h"
15 #include "SkBitmapCache.h"
16 #include "SkGr.h"
17 #include "SkRect.h"
18
19 // since we call lockPixels recursively on fBitmap, we need a distinct mutex,
20 // to avoid deadlock with the default one provided by SkPixelRef.
21 SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
22
23 SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
24     : INHERITED(info, &gROLockPixelsPixelRefMutex) {}
25
26 SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
27
28 bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
29     fBitmap.reset();
30 //    SkDebugf("---------- calling readpixels in support of lockpixels\n");
31     if (!this->onReadPixels(&fBitmap, NULL)) {
32         SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
33         return false;
34     }
35     fBitmap.lockPixels();
36     if (NULL == fBitmap.getPixels()) {
37         return false;
38     }
39
40     rec->fPixels = fBitmap.getPixels();
41     rec->fColorTable = NULL;
42     rec->fRowBytes = fBitmap.rowBytes();
43     return true;
44 }
45
46 void SkROLockPixelsPixelRef::onUnlockPixels() {
47     fBitmap.unlockPixels();
48 }
49
50 bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
51     return false;
52 }
53
54 ///////////////////////////////////////////////////////////////////////////////
55
56 static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorType dstCT,
57                                                   const SkIRect* subset) {
58     if (NULL == texture || kUnknown_SkColorType == dstCT) {
59         return NULL;
60     }
61     GrContext* context = texture->getContext();
62     if (NULL == context) {
63         return NULL;
64     }
65     GrSurfaceDesc desc;
66
67     SkIRect srcRect;
68
69     if (!subset) {
70         desc.fWidth  = texture->width();
71         desc.fHeight = texture->height();
72         srcRect = SkIRect::MakeWH(texture->width(), texture->height());
73     } else {
74         SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset));
75         // Create a new texture that is the size of subset.
76         desc.fWidth = subset->width();
77         desc.fHeight = subset->height();
78         srcRect = *subset;
79     }
80     desc.fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag;
81     desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType);
82
83     GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
84     if (NULL == dst) {
85         return NULL;
86     }
87
88     // Blink is relying on the above copy being sent to GL immediately in the case when the source
89     // is a WebGL canvas backing store. We could have a TODO to remove this flush flag, but we have
90     // a larger TODO to remove SkGrPixelRef entirely.
91     context->copySurface(dst->asRenderTarget(), texture, srcRect, SkIPoint::Make(0,0),
92                          GrContext::kFlushWrites_PixelOp);
93   
94     SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType);
95     SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
96     SkSafeUnref(dst);
97     return pixelRef;
98 }
99
100 ///////////////////////////////////////////////////////////////////////////////
101
102 SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface) : INHERITED(info) {
103     // For surfaces that are both textures and render targets, the texture owns the
104     // render target but not vice versa. So we ref the texture to keep both alive for
105     // the lifetime of this pixel ref.
106     fSurface = SkSafeRef(surface->asTexture());
107     if (NULL == fSurface) {
108         fSurface = SkSafeRef(surface);
109     }
110
111     if (fSurface) {
112         SkASSERT(info.width() <= fSurface->width());
113         SkASSERT(info.height() <= fSurface->height());
114     }
115 }
116
117 SkGrPixelRef::~SkGrPixelRef() {
118     SkSafeUnref(fSurface);
119 }
120
121 GrTexture* SkGrPixelRef::getTexture() {
122     if (fSurface) {
123         return fSurface->asTexture();
124     }
125     return NULL;
126 }
127
128 SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) {
129     if (NULL == fSurface) {
130         return NULL;
131     }
132
133     // Note that when copying a render-target-backed pixel ref, we
134     // return a texture-backed pixel ref instead.  This is because
135     // render-target pixel refs are usually created in conjunction with
136     // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
137     // independently of that texture.  Texture-backed pixel refs, on the other
138     // hand, own their GrTextures, and are thus self-contained.
139     return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, subset);
140 }
141
142 static bool tryAllocBitmapPixels(SkBitmap* bitmap) {
143     SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
144     if (NULL != allocator) {
145         return allocator->allocPixelRef(bitmap, 0);
146     } else {
147         // DiscardableMemory is not available, fallback to default allocator
148         return bitmap->tryAllocPixels();
149     }
150 }
151
152 bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
153     if (NULL == fSurface || fSurface->wasDestroyed()) {
154         return false;
155     }
156
157     SkIRect bounds;
158     if (subset) {
159         bounds = *subset;
160     } else {
161         bounds = SkIRect::MakeWH(this->info().width(), this->info().height());
162     }
163
164     //Check the cache
165     if(!SkBitmapCache::Find(this->getGenerationID(), bounds, dst)) {
166         //Cache miss
167
168         SkBitmap cachedBitmap;
169         cachedBitmap.setInfo(this->info().makeWH(bounds.width(), bounds.height()));
170
171         // If we can't alloc the pixels, then fail
172         if (!tryAllocBitmapPixels(&cachedBitmap)) {
173             return false;
174         }
175
176         // Try to read the pixels from the surface
177         void* buffer = cachedBitmap.getPixels();
178         bool readPixelsOk = fSurface->readPixels(bounds.fLeft, bounds.fTop,
179                                 bounds.width(), bounds.height(),
180                                 kSkia8888_GrPixelConfig,
181                                 buffer, cachedBitmap.rowBytes());
182
183         if (!readPixelsOk) {
184             return false;
185         }
186
187         // If we are here, pixels were read correctly from the surface.
188         cachedBitmap.setImmutable();
189         //Add to the cache
190         SkBitmapCache::Add(this->getGenerationID(), bounds, cachedBitmap);
191
192         dst->swap(cachedBitmap);
193     }
194
195     return true;
196
197 }