Line data Source code
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 :
17 0 : GrSurface::~GrSurface() {
18 0 : if (fLastOpList) {
19 0 : fLastOpList->clearTarget();
20 : }
21 0 : SkSafeUnref(fLastOpList);
22 :
23 : // check that invokeReleaseProc has been called (if needed)
24 0 : SkASSERT(NULL == fReleaseProc);
25 0 : }
26 :
27 0 : size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
28 : size_t size;
29 :
30 0 : int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
31 0 : int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
32 :
33 0 : bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
34 0 : if (isRenderTarget) {
35 : // We own one color value for each MSAA sample.
36 0 : int colorValuesPerPixel = SkTMax(1, desc.fSampleCnt);
37 0 : if (desc.fSampleCnt) {
38 : // Worse case, we own the resolve buffer so that is one more sample per pixel.
39 0 : colorValuesPerPixel += 1;
40 : }
41 0 : SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
42 0 : SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
43 0 : 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 0 : size = colorValuesPerPixel * colorBytes;
50 0 : size += colorBytes/3; // in case we have to mipmap
51 : } else {
52 0 : if (GrPixelConfigIsCompressed(desc.fConfig)) {
53 0 : size = GrCompressedFormatDataSize(desc.fConfig, width, height);
54 : } else {
55 0 : size = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
56 : }
57 :
58 0 : size += size/3; // in case we have to mipmap
59 : }
60 :
61 0 : return size;
62 : }
63 :
64 0 : size_t GrSurface::ComputeSize(const GrSurfaceDesc& desc,
65 : int colorSamplesPerPixel,
66 : bool hasMIPMaps,
67 : bool useNextPow2) {
68 : size_t colorSize;
69 :
70 0 : int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
71 0 : int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
72 :
73 0 : SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);
74 0 : if (GrPixelConfigIsCompressed(desc.fConfig)) {
75 0 : colorSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
76 : } else {
77 0 : colorSize = (size_t) width * height * GrBytesPerPixel(desc.fConfig);
78 : }
79 0 : SkASSERT(colorSize > 0);
80 :
81 0 : size_t finalSize = colorSamplesPerPixel * colorSize;
82 :
83 0 : 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 0 : finalSize += colorSize/3;
87 : }
88 :
89 0 : SkASSERT(finalSize <= WorstCaseSize(desc, useNextPow2));
90 0 : return finalSize;
91 : }
92 :
93 0 : 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 0 : if (!*rowBytes) {
100 0 : *rowBytes = *width * bpp;
101 : }
102 :
103 0 : SkIRect subRect = SkIRect::MakeXYWH(*left, *top, *width, *height);
104 0 : SkIRect bounds = SkIRect::MakeWH(surfaceWidth, surfaceHeight);
105 :
106 0 : if (!subRect.intersect(bounds)) {
107 0 : return false;
108 : }
109 0 : *data = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(*data) +
110 0 : (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
111 :
112 0 : *left = subRect.fLeft;
113 0 : *top = subRect.fTop;
114 0 : *width = subRect.width();
115 0 : *height = subRect.height();
116 0 : return true;
117 : }
118 :
119 0 : 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 0 : rowBytes);
127 : }
128 :
129 0 : 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 0 : data, rowBytes);
137 : }
138 :
139 :
140 : //////////////////////////////////////////////////////////////////////////////
141 :
142 0 : bool GrSurface::hasPendingRead() const {
143 0 : const GrTexture* thisTex = this->asTexture();
144 0 : if (thisTex && thisTex->internalHasPendingRead()) {
145 0 : return true;
146 : }
147 0 : const GrRenderTarget* thisRT = this->asRenderTarget();
148 0 : if (thisRT && thisRT->internalHasPendingRead()) {
149 0 : return true;
150 : }
151 0 : return false;
152 : }
153 :
154 0 : bool GrSurface::hasPendingWrite() const {
155 0 : const GrTexture* thisTex = this->asTexture();
156 0 : if (thisTex && thisTex->internalHasPendingWrite()) {
157 0 : return true;
158 : }
159 0 : const GrRenderTarget* thisRT = this->asRenderTarget();
160 0 : if (thisRT && thisRT->internalHasPendingWrite()) {
161 0 : return true;
162 : }
163 0 : return false;
164 : }
165 :
166 0 : bool GrSurface::hasPendingIO() const {
167 0 : const GrTexture* thisTex = this->asTexture();
168 0 : if (thisTex && thisTex->internalHasPendingIO()) {
169 0 : return true;
170 : }
171 0 : const GrRenderTarget* thisRT = this->asRenderTarget();
172 0 : if (thisRT && thisRT->internalHasPendingIO()) {
173 0 : return true;
174 : }
175 0 : return false;
176 : }
177 :
178 0 : void GrSurface::onRelease() {
179 0 : this->invokeReleaseProc();
180 0 : this->INHERITED::onRelease();
181 0 : }
182 :
183 0 : void GrSurface::onAbandon() {
184 0 : this->invokeReleaseProc();
185 0 : this->INHERITED::onAbandon();
186 0 : }
187 :
188 0 : void GrSurface::setLastOpList(GrOpList* opList) {
189 0 : if (fLastOpList) {
190 : // The non-MDB world never closes so we can't check this condition
191 : #ifdef ENABLE_MDB
192 : SkASSERT(fLastOpList->isClosed());
193 : #endif
194 0 : fLastOpList->clearTarget();
195 : }
196 :
197 0 : SkRefCnt_SafeAssign(fLastOpList, opList);
198 0 : }
|