1 /*
2  * Copyright 2012 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 "GrSurface.h"
9 #include "GrContext.h"
10 #include "GrOpList.h"
11 #include "GrRenderTarget.h"
12 #include "GrResourceProvider.h"
13 #include "GrSurfacePriv.h"
14 #include "GrTexture.h"
15 
16 #include "SkGr.h"
17 #include "SkMathPriv.h"
18 
WorstCaseSize(const GrSurfaceDesc & desc,bool useNextPow2)19 size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
20     size_t size;
21 
22     int width = useNextPow2
23                 ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fWidth))
24                 : desc.fWidth;
25     int height = useNextPow2
26                 ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fHeight))
27                 : desc.fHeight;
28 
29     bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
30     if (isRenderTarget) {
31         // We own one color value for each MSAA sample.
32         SkASSERT(desc.fSampleCnt >= 1);
33         int colorValuesPerPixel = desc.fSampleCnt;
34         if (desc.fSampleCnt > 1) {
35             // Worse case, we own the resolve buffer so that is one more sample per pixel.
36             colorValuesPerPixel += 1;
37         }
38         SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
39         SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
40         size_t colorBytes = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
41 
42         // This would be a nice assert to have (i.e., we aren't creating 0 width/height surfaces).
43         // Unfortunately Chromium seems to want to do this.
44         //SkASSERT(colorBytes > 0);
45 
46         size = colorValuesPerPixel * colorBytes;
47         size += colorBytes/3; // in case we have to mipmap
48     } else {
49         if (GrPixelConfigIsCompressed(desc.fConfig)) {
50             size = GrCompressedFormatDataSize(desc.fConfig, width, height);
51         } else {
52             size = (size_t)width * height * GrBytesPerPixel(desc.fConfig);
53         }
54 
55         size += size/3;  // in case we have to mipmap
56     }
57 
58     return size;
59 }
60 
ComputeSize(GrPixelConfig config,int width,int height,int colorSamplesPerPixel,GrMipMapped mipMapped,bool useNextPow2)61 size_t GrSurface::ComputeSize(GrPixelConfig config,
62                               int width,
63                               int height,
64                               int colorSamplesPerPixel,
65                               GrMipMapped mipMapped,
66                               bool useNextPow2) {
67     size_t colorSize;
68 
69     width = useNextPow2
70             ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(width))
71             : width;
72     height = useNextPow2
73             ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(height))
74             : height;
75 
76     SkASSERT(kUnknown_GrPixelConfig != config);
77     if (GrPixelConfigIsCompressed(config)) {
78         colorSize = GrCompressedFormatDataSize(config, width, height);
79     } else {
80         colorSize = (size_t)width * height * GrBytesPerPixel(config);
81     }
82     SkASSERT(colorSize > 0);
83 
84     size_t finalSize = colorSamplesPerPixel * colorSize;
85 
86     if (GrMipMapped::kYes == mipMapped) {
87         // We don't have to worry about the mipmaps being a different size than
88         // we'd expect because we never change fDesc.fWidth/fHeight.
89         finalSize += colorSize/3;
90     }
91     return finalSize;
92 }
93 
adjust_params(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,T ** data,size_t * rowBytes)94 template<typename T> static bool adjust_params(int surfaceWidth,
95                                                int surfaceHeight,
96                                                size_t bpp,
97                                                int* left, int* top, int* width, int* height,
98                                                T** data,
99                                                size_t* rowBytes) {
100     if (!*rowBytes) {
101         *rowBytes = *width * bpp;
102     }
103 
104     SkIRect subRect = SkIRect::MakeXYWH(*left, *top, *width, *height);
105     SkIRect bounds = SkIRect::MakeWH(surfaceWidth, surfaceHeight);
106 
107     if (!subRect.intersect(bounds)) {
108         return false;
109     }
110     *data = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(*data) +
111             (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
112 
113     *left = subRect.fLeft;
114     *top = subRect.fTop;
115     *width = subRect.width();
116     *height = subRect.height();
117     return true;
118 }
119 
AdjustReadPixelParams(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,void ** data,size_t * rowBytes)120 bool GrSurfacePriv::AdjustReadPixelParams(int surfaceWidth,
121                                           int surfaceHeight,
122                                           size_t bpp,
123                                           int* left, int* top, int* width, int* height,
124                                           void** data,
125                                           size_t* rowBytes) {
126     return adjust_params<void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height, data,
127                                rowBytes);
128 }
129 
AdjustWritePixelParams(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,const void ** data,size_t * rowBytes)130 bool GrSurfacePriv::AdjustWritePixelParams(int surfaceWidth,
131                                            int surfaceHeight,
132                                            size_t bpp,
133                                            int* left, int* top, int* width, int* height,
134                                            const void** data,
135                                            size_t* rowBytes) {
136     return adjust_params<const void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height,
137                                      data, rowBytes);
138 }
139 
140 
141 //////////////////////////////////////////////////////////////////////////////
142 
hasPendingRead() const143 bool GrSurface::hasPendingRead() const {
144     const GrTexture* thisTex = this->asTexture();
145     if (thisTex && thisTex->internalHasPendingRead()) {
146         return true;
147     }
148     const GrRenderTarget* thisRT = this->asRenderTarget();
149     if (thisRT && thisRT->internalHasPendingRead()) {
150         return true;
151     }
152     return false;
153 }
154 
hasPendingWrite() const155 bool GrSurface::hasPendingWrite() const {
156     const GrTexture* thisTex = this->asTexture();
157     if (thisTex && thisTex->internalHasPendingWrite()) {
158         return true;
159     }
160     const GrRenderTarget* thisRT = this->asRenderTarget();
161     if (thisRT && thisRT->internalHasPendingWrite()) {
162         return true;
163     }
164     return false;
165 }
166 
hasPendingIO() const167 bool GrSurface::hasPendingIO() const {
168     const GrTexture* thisTex = this->asTexture();
169     if (thisTex && thisTex->internalHasPendingIO()) {
170         return true;
171     }
172     const GrRenderTarget* thisRT = this->asRenderTarget();
173     if (thisRT && thisRT->internalHasPendingIO()) {
174         return true;
175     }
176     return false;
177 }
178 
onRelease()179 void GrSurface::onRelease() {
180     this->INHERITED::onRelease();
181 }
182 
onAbandon()183 void GrSurface::onAbandon() {
184     this->INHERITED::onAbandon();
185 }
186