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 "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