Home | History | Annotate | Download | only in gpu
      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 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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    166 void GrSurface::flushWrites() {
    167     if (!this->wasDestroyed()) {
    168         this->getContext()->flushSurfaceWrites(this);
    169     }
    170 }
    171 
    172 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 
    184 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 
    196 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 
    208 void GrSurface::onRelease() {
    209     this->invokeReleaseProc();
    210     this->INHERITED::onRelease();
    211 }
    212 
    213 void GrSurface::onAbandon() {
    214     this->invokeReleaseProc();
    215     this->INHERITED::onAbandon();
    216 }
    217 
    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