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 "GrSurfacePriv.h" 11 12 #include "SkBitmap.h" 13 #include "SkGrPriv.h" 14 #include "SkImageEncoder.h" 15 #include <stdio.h> 16 17 size_t GrSurface::WorseCaseSize(const GrSurfaceDesc& desc) { 18 size_t size; 19 20 bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); 21 if (isRenderTarget) { 22 // We own one color value for each MSAA sample. 23 int colorValuesPerPixel = SkTMax(1, desc.fSampleCnt); 24 if (desc.fSampleCnt) { 25 // Worse case, we own the resolve buffer so that is one more sample per pixel. 26 colorValuesPerPixel += 1; 27 } 28 SkASSERT(kUnknown_GrPixelConfig != desc.fConfig); 29 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); 30 size_t colorBytes = GrBytesPerPixel(desc.fConfig); 31 SkASSERT(colorBytes > 0); 32 size = colorValuesPerPixel * desc.fWidth * desc.fHeight * colorBytes; 33 } else { 34 if (GrPixelConfigIsCompressed(desc.fConfig)) { 35 size = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight); 36 } else { 37 size = (size_t) desc.fWidth * desc.fHeight * GrBytesPerPixel(desc.fConfig); 38 } 39 40 size += size/3; // in case we have to mipmap 41 } 42 43 return size; 44 } 45 46 template<typename T> static bool adjust_params(int surfaceWidth, 47 int surfaceHeight, 48 size_t bpp, 49 int* left, int* top, int* width, int* height, 50 T** data, 51 size_t* rowBytes) { 52 if (!*rowBytes) { 53 *rowBytes = *width * bpp; 54 } 55 56 SkIRect subRect = SkIRect::MakeXYWH(*left, *top, *width, *height); 57 SkIRect bounds = SkIRect::MakeWH(surfaceWidth, surfaceHeight); 58 59 if (!subRect.intersect(bounds)) { 60 return false; 61 } 62 *data = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(*data) + 63 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp); 64 65 *left = subRect.fLeft; 66 *top = subRect.fTop; 67 *width = subRect.width(); 68 *height = subRect.height(); 69 return true; 70 } 71 72 bool GrSurfacePriv::AdjustReadPixelParams(int surfaceWidth, 73 int surfaceHeight, 74 size_t bpp, 75 int* left, int* top, int* width, int* height, 76 void** data, 77 size_t* rowBytes) { 78 return adjust_params<void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height, data, 79 rowBytes); 80 } 81 82 bool GrSurfacePriv::AdjustWritePixelParams(int surfaceWidth, 83 int surfaceHeight, 84 size_t bpp, 85 int* left, int* top, int* width, int* height, 86 const void** data, 87 size_t* rowBytes) { 88 return adjust_params<const void>(surfaceWidth, surfaceHeight, bpp, left, top, width, height, 89 data, rowBytes); 90 } 91 92 93 ////////////////////////////////////////////////////////////////////////////// 94 95 bool GrSurface::writePixels(int left, int top, int width, int height, 96 GrPixelConfig config, const void* buffer, size_t rowBytes, 97 uint32_t pixelOpsFlags) { 98 // go through context so that all necessary flushing occurs 99 GrContext* context = this->getContext(); 100 if (nullptr == context) { 101 return false; 102 } 103 return context->writeSurfacePixels(this, left, top, width, height, config, buffer, rowBytes, 104 pixelOpsFlags); 105 } 106 107 bool GrSurface::readPixels(int left, int top, int width, int height, 108 GrPixelConfig config, void* buffer, size_t rowBytes, 109 uint32_t pixelOpsFlags) { 110 // go through context so that all necessary flushing occurs 111 GrContext* context = this->getContext(); 112 if (nullptr == context) { 113 return false; 114 } 115 return context->readSurfacePixels(this, left, top, width, height, config, buffer, 116 rowBytes, pixelOpsFlags); 117 } 118 119 SkImageInfo GrSurface::info(SkAlphaType alphaType) const { 120 SkColorType colorType; 121 SkColorProfileType profileType; 122 if (!GrPixelConfig2ColorAndProfileType(this->config(), &colorType, &profileType)) { 123 sk_throw(); 124 } 125 return SkImageInfo::Make(this->width(), this->height(), colorType, alphaType, 126 profileType); 127 } 128 129 // TODO: This should probably be a non-member helper function. It might only be needed in 130 // debug or developer builds. 131 bool GrSurface::savePixels(const char* filename) { 132 SkBitmap bm; 133 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(this->width(), this->height()))) { 134 return false; 135 } 136 137 bool result = this->readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig, 138 bm.getPixels()); 139 if (!result) { 140 SkDebugf("------ failed to read pixels for %s\n", filename); 141 return false; 142 } 143 144 // remove any previous version of this file 145 remove(filename); 146 147 if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) { 148 SkDebugf("------ failed to encode %s\n", filename); 149 remove(filename); // remove any partial file 150 return false; 151 } 152 153 return true; 154 } 155 156 void GrSurface::flushWrites() { 157 if (!this->wasDestroyed()) { 158 this->getContext()->flushSurfaceWrites(this); 159 } 160 } 161 162 void GrSurface::prepareForExternalIO() { 163 if (!this->wasDestroyed()) { 164 this->getContext()->prepareSurfaceForExternalIO(this); 165 } 166 } 167 168 bool GrSurface::hasPendingRead() const { 169 const GrTexture* thisTex = this->asTexture(); 170 if (thisTex && thisTex->internalHasPendingRead()) { 171 return true; 172 } 173 const GrRenderTarget* thisRT = this->asRenderTarget(); 174 if (thisRT && thisRT->internalHasPendingRead()) { 175 return true; 176 } 177 return false; 178 } 179 180 bool GrSurface::hasPendingWrite() const { 181 const GrTexture* thisTex = this->asTexture(); 182 if (thisTex && thisTex->internalHasPendingWrite()) { 183 return true; 184 } 185 const GrRenderTarget* thisRT = this->asRenderTarget(); 186 if (thisRT && thisRT->internalHasPendingWrite()) { 187 return true; 188 } 189 return false; 190 } 191 192 bool GrSurface::hasPendingIO() const { 193 const GrTexture* thisTex = this->asTexture(); 194 if (thisTex && thisTex->internalHasPendingIO()) { 195 return true; 196 } 197 const GrRenderTarget* thisRT = this->asRenderTarget(); 198 if (thisRT && thisRT->internalHasPendingIO()) { 199 return true; 200 } 201 return false; 202 } 203 204 void GrSurface::onRelease() { 205 this->invokeReleaseProc(); 206 this->INHERITED::onRelease(); 207 } 208 209 void GrSurface::onAbandon() { 210 this->invokeReleaseProc(); 211 this->INHERITED::onAbandon(); 212 } 213