1 /*
2 * Copyright 2016 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 "GrTextureContext.h"
9 #include "GrDrawingManager.h"
10 #include "GrResourceProvider.h"
11 #include "GrTextureOpList.h"
12
13 #include "../private/GrAuditTrail.h"
14
15 #define ASSERT_SINGLE_OWNER \
16 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
17 #define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
18
GrTextureContext(GrContext * context,GrDrawingManager * drawingMgr,sk_sp<GrTextureProxy> textureProxy,sk_sp<SkColorSpace> colorSpace,GrAuditTrail * auditTrail,GrSingleOwner * singleOwner)19 GrTextureContext::GrTextureContext(GrContext* context,
20 GrDrawingManager* drawingMgr,
21 sk_sp<GrTextureProxy> textureProxy,
22 sk_sp<SkColorSpace> colorSpace,
23 GrAuditTrail* auditTrail,
24 GrSingleOwner* singleOwner)
25 : GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
26 , fTextureProxy(std::move(textureProxy))
27 , fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList())) {
28 SkDEBUGCODE(this->validate();)
29 }
30
31 #ifdef SK_DEBUG
validate() const32 void GrTextureContext::validate() const {
33 SkASSERT(fTextureProxy);
34 fTextureProxy->validate(fContext);
35
36 if (fOpList && !fOpList->isClosed()) {
37 SkASSERT(fTextureProxy->getLastOpList() == fOpList);
38 }
39 }
40 #endif
41
~GrTextureContext()42 GrTextureContext::~GrTextureContext() {
43 ASSERT_SINGLE_OWNER
44 SkSafeUnref(fOpList);
45 }
46
asRenderTargetProxy()47 GrRenderTargetProxy* GrTextureContext::asRenderTargetProxy() {
48 // If the proxy can return an RTProxy it should've been wrapped in a RTContext
49 SkASSERT(!fTextureProxy->asRenderTargetProxy());
50 return nullptr;
51 }
52
asRenderTargetProxyRef()53 sk_sp<GrRenderTargetProxy> GrTextureContext::asRenderTargetProxyRef() {
54 // If the proxy can return an RTProxy it should've been wrapped in a RTContext
55 SkASSERT(!fTextureProxy->asRenderTargetProxy());
56 return nullptr;
57 }
58
getOpList()59 GrTextureOpList* GrTextureContext::getOpList() {
60 ASSERT_SINGLE_OWNER
61 SkDEBUGCODE(this->validate();)
62
63 if (!fOpList || fOpList->isClosed()) {
64 fOpList = this->drawingManager()->newOpList(fTextureProxy.get());
65 }
66
67 return fOpList;
68 }
69
70 // TODO: move this (and GrRenderTargetContext::copy) to GrSurfaceContext?
onCopy(GrSurfaceProxy * srcProxy,const SkIRect & srcRect,const SkIPoint & dstPoint)71 bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy,
72 const SkIRect& srcRect,
73 const SkIPoint& dstPoint) {
74 ASSERT_SINGLE_OWNER
75 RETURN_FALSE_IF_ABANDONED
76 SkDEBUGCODE(this->validate();)
77 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copy");
78
79 // TODO: defer instantiation until flush time
80 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
81 if (!src) {
82 return false;
83 }
84
85 #ifndef ENABLE_MDB
86 // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
87 // execute the copy immediately. Ensure the data is ready.
88 src->flushWrites();
89 #endif
90
91 // TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
92 sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
93 if (!tex) {
94 return false;
95 }
96
97 GrTextureOpList* opList = this->getOpList();
98 bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
99
100 #ifndef ENABLE_MDB
101 GrOpFlushState flushState(fContext->getGpu(), nullptr);
102 opList->prepareOps(&flushState);
103 opList->executeOps(&flushState);
104 opList->reset();
105 #endif
106
107 return result;
108 }
109
110 // TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext?
onReadPixels(const SkImageInfo & dstInfo,void * dstBuffer,size_t dstRowBytes,int x,int y,uint32_t flags)111 bool GrTextureContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
112 size_t dstRowBytes, int x, int y, uint32_t flags) {
113 // TODO: teach GrTexture to take ImageInfo directly to specify the src pixels
114 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
115 if (kUnknown_GrPixelConfig == config) {
116 return false;
117 }
118
119 // TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
120 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
121 flags |= GrContext::kUnpremul_PixelOpsFlag;
122 }
123
124 // Deferral of the VRAM resources must end in this instance anyway
125 sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
126 if (!tex) {
127 return false;
128 }
129
130 return tex->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(),
131 config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags);
132 }
133
134 // TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext?
onWritePixels(const SkImageInfo & srcInfo,const void * srcBuffer,size_t srcRowBytes,int x,int y,uint32_t flags)135 bool GrTextureContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
136 size_t srcRowBytes, int x, int y,
137 uint32_t flags) {
138 // TODO: teach GrTexture to take ImageInfo directly to specify the src pixels
139 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
140 if (kUnknown_GrPixelConfig == config) {
141 return false;
142 }
143 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
144 flags |= GrContext::kUnpremul_PixelOpsFlag;
145 }
146
147 // Deferral of the VRAM resources must end in this instance anyway
148 sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
149 if (!tex) {
150 return false;
151 }
152
153 return tex->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(),
154 config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags);
155 }
156