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 "GrSurfacePriv.h"
10
11#include "SkBitmap.h"
12#include "SkGr.h"
13#include "SkImageEncoder.h"
14#include <stdio.h>
15
16bool GrSurface::writePixels(int left, int top, int width, int height,
17                            GrPixelConfig config, const void* buffer, size_t rowBytes,
18                            uint32_t pixelOpsFlags) {
19    // go through context so that all necessary flushing occurs
20    GrContext* context = this->getContext();
21    if (NULL == context) {
22        return false;
23    }
24    return context->writeSurfacePixels(this, left, top, width, height, config, buffer, rowBytes,
25                                       pixelOpsFlags);
26}
27
28bool GrSurface::readPixels(int left, int top, int width, int height,
29                           GrPixelConfig config, void* buffer, size_t rowBytes,
30                           uint32_t pixelOpsFlags) {
31    // go through context so that all necessary flushing occurs
32    GrContext* context = this->getContext();
33    if (NULL == context) {
34        return false;
35    }
36    GrRenderTarget* target = this->asRenderTarget();
37    if (target) {
38        return context->readRenderTargetPixels(target, left, top, width, height, config, buffer,
39                                               rowBytes, pixelOpsFlags);
40    }
41    return false;
42}
43
44SkImageInfo GrSurface::info() const {
45    SkColorType colorType;
46    SkColorProfileType profileType;
47    if (!GrPixelConfig2ColorAndProfileType(this->config(), &colorType, &profileType)) {
48        sk_throw();
49    }
50    return SkImageInfo::Make(this->width(), this->height(), colorType, kPremul_SkAlphaType,
51                             profileType);
52}
53
54// TODO: This should probably be a non-member helper function. It might only be needed in
55// debug or developer builds.
56bool GrSurface::savePixels(const char* filename) {
57    SkBitmap bm;
58    if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(this->width(), this->height()))) {
59        return false;
60    }
61
62    bool result = this->readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
63                                   bm.getPixels());
64    if (!result) {
65        SkDebugf("------ failed to read pixels for %s\n", filename);
66        return false;
67    }
68
69    // remove any previous version of this file
70    remove(filename);
71
72    if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) {
73        SkDebugf("------ failed to encode %s\n", filename);
74        remove(filename);   // remove any partial file
75        return false;
76    }
77
78    return true;
79}
80
81void GrSurface::flushWrites() {
82    if (!this->wasDestroyed()) {
83        this->getContext()->flushSurfaceWrites(this);
84    }
85}
86
87void GrSurface::prepareForExternalRead() {
88    if (!this->wasDestroyed()) {
89        this->getContext()->prepareSurfaceForExternalRead(this);
90    }
91}
92
93bool GrSurface::hasPendingRead() const {
94    const GrTexture* thisTex = this->asTexture();
95    if (thisTex && thisTex->internalHasPendingRead()) {
96        return true;
97    }
98    const GrRenderTarget* thisRT = this->asRenderTarget();
99    if (thisRT && thisRT->internalHasPendingRead()) {
100        return true;
101    }
102    return false;
103}
104
105bool GrSurface::hasPendingWrite() const {
106    const GrTexture* thisTex = this->asTexture();
107    if (thisTex && thisTex->internalHasPendingWrite()) {
108        return true;
109    }
110    const GrRenderTarget* thisRT = this->asRenderTarget();
111    if (thisRT && thisRT->internalHasPendingWrite()) {
112        return true;
113    }
114    return false;
115}
116
117bool GrSurface::hasPendingIO() const {
118    const GrTexture* thisTex = this->asTexture();
119    if (thisTex && thisTex->internalHasPendingIO()) {
120        return true;
121    }
122    const GrRenderTarget* thisRT = this->asRenderTarget();
123    if (thisRT && thisRT->internalHasPendingIO()) {
124        return true;
125    }
126    return false;
127}
128