blob: c3ac224a0440f8f9e7c21e4ba2e61b61f04743c4 [file] [log] [blame]
robertphillips@google.com7d501ab2012-06-21 21:09:06 +00001/*
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"
bsalomonf276ac52015-10-09 13:36:42 -07009#include "GrContext.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040010#include "GrOpList.h"
bsalomonafbf2d62014-09-30 12:18:44 -070011#include "GrSurfacePriv.h"
robertphillips@google.com7d501ab2012-06-21 21:09:06 +000012
bsalomonf276ac52015-10-09 13:36:42 -070013#include "SkGrPriv.h"
Robert Phillipsb4460882016-11-17 14:43:51 -050014#include "SkMathPriv.h"
commit-bot@chromium.org6c5d9a12013-09-30 18:05:43 +000015
Robert Phillipsf2361d22016-10-25 14:20:06 -040016GrSurface::~GrSurface() {
17 if (fLastOpList) {
18 fLastOpList->clearTarget();
19 }
20 SkSafeUnref(fLastOpList);
21
22 // check that invokeReleaseProc has been called (if needed)
23 SkASSERT(NULL == fReleaseProc);
24}
25
Robert Phillipsb4460882016-11-17 14:43:51 -050026size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
robertphillips6e83ac72015-08-13 05:19:14 -070027 size_t size;
28
Robert Phillipsb4460882016-11-17 14:43:51 -050029 int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
30 int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
31
robertphillips6e83ac72015-08-13 05:19:14 -070032 bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
33 if (isRenderTarget) {
34 // We own one color value for each MSAA sample.
35 int colorValuesPerPixel = SkTMax(1, desc.fSampleCnt);
36 if (desc.fSampleCnt) {
37 // Worse case, we own the resolve buffer so that is one more sample per pixel.
38 colorValuesPerPixel += 1;
39 }
40 SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
41 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
Robert Phillipsb4460882016-11-17 14:43:51 -050042 size_t colorBytes = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
robertphillips4c56b9f2016-08-17 08:02:51 -070043
Robert Phillipsd6214d42016-11-07 08:23:48 -050044 // This would be a nice assert to have (i.e., we aren't creating 0 width/height surfaces).
45 // Unfortunately Chromium seems to want to do this.
46 //SkASSERT(colorBytes > 0);
47
48 size = colorValuesPerPixel * colorBytes;
49 size += colorBytes/3; // in case we have to mipmap
robertphillips6e83ac72015-08-13 05:19:14 -070050 } else {
51 if (GrPixelConfigIsCompressed(desc.fConfig)) {
Robert Phillipsb4460882016-11-17 14:43:51 -050052 size = GrCompressedFormatDataSize(desc.fConfig, width, height);
robertphillips6e83ac72015-08-13 05:19:14 -070053 } else {
Robert Phillipsb4460882016-11-17 14:43:51 -050054 size = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
robertphillips6e83ac72015-08-13 05:19:14 -070055 }
56
57 size += size/3; // in case we have to mipmap
58 }
59
60 return size;
61}
62
Robert Phillipsd6214d42016-11-07 08:23:48 -050063size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc,
64 int colorSamplesPerPixel,
Robert Phillipsb4460882016-11-17 14:43:51 -050065 bool hasMIPMaps,
66 bool useNextPow2) {
Robert Phillipsd6214d42016-11-07 08:23:48 -050067 size_t colorSize;
68
Robert Phillipsb4460882016-11-17 14:43:51 -050069 int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
70 int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
71
Robert Phillipsd6214d42016-11-07 08:23:48 -050072 SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
73 if (GrPixelConfigIsCompressed(desc.fConfig)) {
Robert Phillipsb4460882016-11-17 14:43:51 -050074 colorSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
Robert Phillipsd6214d42016-11-07 08:23:48 -050075 } else {
Robert Phillipsb4460882016-11-17 14:43:51 -050076 colorSize = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
Robert Phillipsd6214d42016-11-07 08:23:48 -050077 }
78 SkASSERT(colorSize > 0);
79
80 size_t finalSize = colorSamplesPerPixel * colorSize;
81
82 if (hasMIPMaps) {
83 // We don't have to worry about the mipmaps being a different size than
84 // we'd expect because we never change fDesc.fWidth/fHeight.
85 finalSize += colorSize/3;
86 }
87
Robert Phillipsb4460882016-11-17 14:43:51 -050088 SkASSERT(finalSize <= WorstCaseSize(desc, useNextPow2));
Robert Phillipsd6214d42016-11-07 08:23:48 -050089 return finalSize;
90}
91
bsalomone8d21e82015-07-16 08:23:13 -070092template<typename T> static bool adjust_params(int surfaceWidth,
93 int surfaceHeight,
94 size_t bpp,
95 int* left, int* top, int* width, int* height,
96 T** data,
97 size_t* rowBytes) {
98 if (!*rowBytes) {
99 *rowBytes = *width * bpp;
100 }
101
102 SkIRect subRect = SkIRect::MakeXYWH(*left, *top, *width, *height);
103 SkIRect bounds = SkIRect::MakeWH(surfaceWidth, surfaceHeight);
104
105 if (!subRect.intersect(bounds)) {
106 return false;
107 }
108 *data = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(*data) +
109 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
110
111 *left = subRect.fLeft;
112 *top = subRect.fTop;
113 *width = subRect.width();
114 *height = subRect.height();
115 return true;
116}
117
118bool GrSurfacePriv::AdjustReadPixelParams(int surfaceWidth,
119 int surfaceHeight,
120 size_t bpp,
121 int* left, int* top, int* width, int* height,
122 void** data,
123 size_t* rowBytes) {
124 return adjust_params<void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height, data,
125 rowBytes);
126}
127
128bool GrSurfacePriv::AdjustWritePixelParams(int surfaceWidth,
129 int surfaceHeight,
130 size_t bpp,
131 int* left, int* top, int* width, int* height,
132 const void** data,
133 size_t* rowBytes) {
134 return adjust_params<const void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height,
135 data, rowBytes);
136}
137
138
139//////////////////////////////////////////////////////////////////////////////
140
Brian Osmanb62ea222016-12-22 11:12:16 -0500141bool GrSurface::writePixels(SkColorSpace* dstColorSpace, int left, int top, int width, int height,
142 GrPixelConfig config, SkColorSpace* srcColorSpace, const void* buffer,
143 size_t rowBytes, uint32_t pixelOpsFlags) {
bsalomon81beccc2014-10-13 12:32:55 -0700144 // go through context so that all necessary flushing occurs
145 GrContext* context = this->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700146 if (nullptr == context) {
bsalomon81beccc2014-10-13 12:32:55 -0700147 return false;
148 }
Brian Osmanb62ea222016-12-22 11:12:16 -0500149 return context->writeSurfacePixels(this, dstColorSpace, left, top, width, height, config,
150 srcColorSpace, buffer, rowBytes, pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700151}
152
Brian Osmanb62ea222016-12-22 11:12:16 -0500153bool GrSurface::readPixels(SkColorSpace* srcColorSpace, int left, int top, int width, int height,
154 GrPixelConfig config, SkColorSpace* dstColorSpace, void* buffer,
155 size_t rowBytes, uint32_t pixelOpsFlags) {
bsalomon81beccc2014-10-13 12:32:55 -0700156 // go through context so that all necessary flushing occurs
157 GrContext* context = this->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700158 if (nullptr == context) {
bsalomon81beccc2014-10-13 12:32:55 -0700159 return false;
160 }
Brian Osmanb62ea222016-12-22 11:12:16 -0500161 return context->readSurfacePixels(this, srcColorSpace, left, top, width, height, config,
162 dstColorSpace, buffer, rowBytes, pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700163}
164
bsalomonf80bfed2014-10-07 05:56:02 -0700165void GrSurface::flushWrites() {
166 if (!this->wasDestroyed()) {
167 this->getContext()->flushSurfaceWrites(this);
168 }
169}
170
bsalomon8d034a12014-09-22 12:21:08 -0700171bool GrSurface::hasPendingRead() const {
172 const GrTexture* thisTex = this->asTexture();
173 if (thisTex && thisTex->internalHasPendingRead()) {
174 return true;
175 }
176 const GrRenderTarget* thisRT = this->asRenderTarget();
177 if (thisRT && thisRT->internalHasPendingRead()) {
178 return true;
179 }
180 return false;
181}
182
183bool GrSurface::hasPendingWrite() const {
184 const GrTexture* thisTex = this->asTexture();
185 if (thisTex && thisTex->internalHasPendingWrite()) {
186 return true;
187 }
188 const GrRenderTarget* thisRT = this->asRenderTarget();
189 if (thisRT && thisRT->internalHasPendingWrite()) {
190 return true;
191 }
192 return false;
193}
194
195bool GrSurface::hasPendingIO() const {
196 const GrTexture* thisTex = this->asTexture();
197 if (thisTex && thisTex->internalHasPendingIO()) {
198 return true;
199 }
200 const GrRenderTarget* thisRT = this->asRenderTarget();
201 if (thisRT && thisRT->internalHasPendingIO()) {
202 return true;
203 }
204 return false;
205}
reedde499882015-06-18 13:41:40 -0700206
207void GrSurface::onRelease() {
208 this->invokeReleaseProc();
209 this->INHERITED::onRelease();
210}
211
212void GrSurface::onAbandon() {
213 this->invokeReleaseProc();
214 this->INHERITED::onAbandon();
215}
Robert Phillipsf2361d22016-10-25 14:20:06 -0400216
217void GrSurface::setLastOpList(GrOpList* opList) {
218 if (fLastOpList) {
219 // The non-MDB world never closes so we can't check this condition
220#ifdef ENABLE_MDB
221 SkASSERT(fLastOpList->isClosed());
222#endif
223 fLastOpList->clearTarget();
224 }
225
226 SkRefCnt_SafeAssign(fLastOpList, opList);
227}