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 "GrSurfacePriv.h"
12 #include "GrTexture.h"
13
14 #include "SkGr.h"
15 #include "SkMathPriv.h"
16
~GrSurface()17 GrSurface::~GrSurface() {
18 if (fLastOpList) {
19 fLastOpList->clearTarget();
20 }
21 SkSafeUnref(fLastOpList);
22
23 // check that invokeReleaseProc has been called (if needed)
24 SkASSERT(NULL == fReleaseProc);
25 }
26
WorstCaseSize(const GrSurfaceDesc & desc,bool useNextPow2)27 size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
28 size_t size;
29
30 int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
31 int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
32
33 bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
34 if (isRenderTarget) {
35 // We own one color value for each MSAA sample.
36 int colorValuesPerPixel = SkTMax(1, desc.fSampleCnt);
37 if (desc.fSampleCnt) {
38 // Worse case, we own the resolve buffer so that is one more sample per pixel.
39 colorValuesPerPixel += 1;
40 }
41 SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
42 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
43 size_t colorBytes = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
44
45 // This would be a nice assert to have (i.e., we aren't creating 0 width/height surfaces).
46 // Unfortunately Chromium seems to want to do this.
47 //SkASSERT(colorBytes > 0);
48
49 size = colorValuesPerPixel * colorBytes;
50 size += colorBytes/3; // in case we have to mipmap
51 } else {
52 if (GrPixelConfigIsCompressed(desc.fConfig)) {
53 size = GrCompressedFormatDataSize(desc.fConfig, width, height);
54 } else {
55 size = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
56 }
57
58 size += size/3; // in case we have to mipmap
59 }
60
61 return size;
62 }
63
ComputeSize(const GrSurfaceDesc & desc,int colorSamplesPerPixel,bool hasMIPMaps,bool useNextPow2)64 size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc,
65 int colorSamplesPerPixel,
66 bool hasMIPMaps,
67 bool useNextPow2) {
68 size_t colorSize;
69
70 int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
71 int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
72
73 SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
74 if (GrPixelConfigIsCompressed(desc.fConfig)) {
75 colorSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
76 } else {
77 colorSize = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
78 }
79 SkASSERT(colorSize > 0);
80
81 size_t finalSize = colorSamplesPerPixel * colorSize;
82
83 if (hasMIPMaps) {
84 // We don't have to worry about the mipmaps being a different size than
85 // we'd expect because we never change fDesc.fWidth/fHeight.
86 finalSize += colorSize/3;
87 }
88
89 SkASSERT(finalSize <= WorstCaseSize(desc, useNextPow2));
90 return finalSize;
91 }
92
adjust_params(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,T ** data,size_t * rowBytes)93 template<typename T> static bool adjust_params(int surfaceWidth,
94 int surfaceHeight,
95 size_t bpp,
96 int* left, int* top, int* width, int* height,
97 T** data,
98 size_t* rowBytes) {
99 if (!*rowBytes) {
100 *rowBytes = *width * bpp;
101 }
102
103 SkIRect subRect = SkIRect::MakeXYWH(*left, *top, *width, *height);
104 SkIRect bounds = SkIRect::MakeWH(surfaceWidth, surfaceHeight);
105
106 if (!subRect.intersect(bounds)) {
107 return false;
108 }
109 *data = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(*data) +
110 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
111
112 *left = subRect.fLeft;
113 *top = subRect.fTop;
114 *width = subRect.width();
115 *height = subRect.height();
116 return true;
117 }
118
AdjustReadPixelParams(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,void ** data,size_t * rowBytes)119 bool GrSurfacePriv::AdjustReadPixelParams(int surfaceWidth,
120 int surfaceHeight,
121 size_t bpp,
122 int* left, int* top, int* width, int* height,
123 void** data,
124 size_t* rowBytes) {
125 return adjust_params<void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height, data,
126 rowBytes);
127 }
128
AdjustWritePixelParams(int surfaceWidth,int surfaceHeight,size_t bpp,int * left,int * top,int * width,int * height,const void ** data,size_t * rowBytes)129 bool GrSurfacePriv::AdjustWritePixelParams(int surfaceWidth,
130 int surfaceHeight,
131 size_t bpp,
132 int* left, int* top, int* width, int* height,
133 const void** data,
134 size_t* rowBytes) {
135 return adjust_params<const void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height,
136 data, rowBytes);
137 }
138
139
140 //////////////////////////////////////////////////////////////////////////////
141
writePixels(SkColorSpace * dstColorSpace,int left,int top,int width,int height,GrPixelConfig config,SkColorSpace * srcColorSpace,const void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)142 bool GrSurface::writePixels(SkColorSpace* dstColorSpace, int left, int top, int width, int height,
143 GrPixelConfig config, SkColorSpace* srcColorSpace, const void* buffer,
144 size_t rowBytes, uint32_t pixelOpsFlags) {
145 // go through context so that all necessary flushing occurs
146 GrContext* context = this->getContext();
147 if (nullptr == context) {
148 return false;
149 }
150 return context->writeSurfacePixels(this, dstColorSpace, left, top, width, height, config,
151 srcColorSpace, buffer, rowBytes, pixelOpsFlags);
152 }
153
readPixels(SkColorSpace * srcColorSpace,int left,int top,int width,int height,GrPixelConfig config,SkColorSpace * dstColorSpace,void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)154 bool GrSurface::readPixels(SkColorSpace* srcColorSpace, int left, int top, int width, int height,
155 GrPixelConfig config, SkColorSpace* dstColorSpace, void* buffer,
156 size_t rowBytes, uint32_t pixelOpsFlags) {
157 // go through context so that all necessary flushing occurs
158 GrContext* context = this->getContext();
159 if (nullptr == context) {
160 return false;
161 }
162 return context->readSurfacePixels(this, srcColorSpace, left, top, width, height, config,
163 dstColorSpace, buffer, rowBytes, pixelOpsFlags);
164 }
165
flushWrites()166 void GrSurface::flushWrites() {
167 if (!this->wasDestroyed()) {
168 this->getContext()->flushSurfaceWrites(this);
169 }
170 }
171
hasPendingRead() const172 bool GrSurface::hasPendingRead() const {
173 const GrTexture* thisTex = this->asTexture();
174 if (thisTex && thisTex->internalHasPendingRead()) {
175 return true;
176 }
177 const GrRenderTarget* thisRT = this->asRenderTarget();
178 if (thisRT && thisRT->internalHasPendingRead()) {
179 return true;
180 }
181 return false;
182 }
183
hasPendingWrite() const184 bool GrSurface::hasPendingWrite() const {
185 const GrTexture* thisTex = this->asTexture();
186 if (thisTex && thisTex->internalHasPendingWrite()) {
187 return true;
188 }
189 const GrRenderTarget* thisRT = this->asRenderTarget();
190 if (thisRT && thisRT->internalHasPendingWrite()) {
191 return true;
192 }
193 return false;
194 }
195
hasPendingIO() const196 bool GrSurface::hasPendingIO() const {
197 const GrTexture* thisTex = this->asTexture();
198 if (thisTex && thisTex->internalHasPendingIO()) {
199 return true;
200 }
201 const GrRenderTarget* thisRT = this->asRenderTarget();
202 if (thisRT && thisRT->internalHasPendingIO()) {
203 return true;
204 }
205 return false;
206 }
207
onRelease()208 void GrSurface::onRelease() {
209 this->invokeReleaseProc();
210 this->INHERITED::onRelease();
211 }
212
onAbandon()213 void GrSurface::onAbandon() {
214 this->invokeReleaseProc();
215 this->INHERITED::onAbandon();
216 }
217
setLastOpList(GrOpList * opList)218 void GrSurface::setLastOpList(GrOpList* opList) {
219 if (fLastOpList) {
220 // The non-MDB world never closes so we can't check this condition
221 #ifdef ENABLE_MDB
222 SkASSERT(fLastOpList->isClosed());
223 #endif
224 fLastOpList->clearTarget();
225 }
226
227 SkRefCnt_SafeAssign(fLastOpList, opList);
228 }
229