blob: bc11b4b9c6578b4f571b04c2897cbb4e2200fd3a [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reed@google.comac10a2d2010-12-22 21:39:39 +00009#include "GrGpu.h"
bsalomon@google.com558a75b2011-08-08 17:01:14 +000010
cdalton397536c2016-03-25 12:15:03 -070011#include "GrBuffer.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070012#include "GrCaps.h"
bsalomon@google.com558a75b2011-08-08 17:01:14 +000013#include "GrContext.h"
bsalomon3582d3e2015-02-13 14:20:05 -080014#include "GrGpuResourcePriv.h"
egdaniel0e1853c2016-03-17 11:35:45 -070015#include "GrMesh.h"
kkinnunencabe20c2015-06-01 01:37:26 -070016#include "GrPathRendering.h"
bsalomoncb02b382015-08-12 11:14:50 -070017#include "GrPipeline.h"
bsalomon0ea80f42015-02-11 10:49:59 -080018#include "GrResourceCache.h"
egdanielec00d942015-09-14 12:56:10 -070019#include "GrResourceProvider.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080020#include "GrRenderTargetPriv.h"
egdaniel8dc7c3a2015-04-16 11:22:42 -070021#include "GrStencilAttachment.h"
egdaniel6d901da2015-07-30 12:02:15 -070022#include "GrSurfacePriv.h"
cblume55f2d2d2016-02-26 13:20:48 -080023#include "SkTypes.h"
bsalomoncb8979d2015-05-05 09:51:38 -070024
egdaniel0e1853c2016-03-17 11:35:45 -070025GrMesh& GrMesh::operator =(const GrMesh& di) {
bsalomoncb8979d2015-05-05 09:51:38 -070026 fPrimitiveType = di.fPrimitiveType;
27 fStartVertex = di.fStartVertex;
28 fStartIndex = di.fStartIndex;
29 fVertexCount = di.fVertexCount;
30 fIndexCount = di.fIndexCount;
31
32 fInstanceCount = di.fInstanceCount;
33 fVerticesPerInstance = di.fVerticesPerInstance;
34 fIndicesPerInstance = di.fIndicesPerInstance;
bsalomone64eb572015-05-07 11:35:55 -070035 fMaxInstancesPerDraw = di.fMaxInstancesPerDraw;
bsalomoncb8979d2015-05-05 09:51:38 -070036
37 fVertexBuffer.reset(di.vertexBuffer());
38 fIndexBuffer.reset(di.indexBuffer());
39
40 return *this;
41}
bsalomon@google.com1c13c962011-02-14 16:51:21 +000042
bsalomon@google.comd302f142011-03-03 13:54:13 +000043////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000044
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000045GrGpu::GrGpu(GrContext* context)
joshualitt3322fa42014-11-07 08:48:51 -080046 : fResetTimestamp(kExpiredTimestamp+1)
bsalomon@google.com0a208a12013-06-28 18:57:35 +000047 , fResetBits(kAll_GrBackendState)
cdalton28f45b92016-03-07 13:58:26 -080048 , fMultisampleSpecsAllocator(1)
joshualitt3322fa42014-11-07 08:48:51 -080049 , fContext(context) {
reed@google.comac10a2d2010-12-22 21:39:39 +000050}
51
bsalomoned0bcad2015-05-04 10:36:42 -070052GrGpu::~GrGpu() {}
bsalomon1d89ddc2014-08-19 14:20:58 -070053
bsalomon6e2aad42016-04-01 11:54:31 -070054void GrGpu::disconnect(DisconnectType) {}
reed@google.comac10a2d2010-12-22 21:39:39 +000055
bsalomon@google.comd302f142011-03-03 13:54:13 +000056////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000057
bsalomon045802d2015-10-20 07:58:01 -070058bool GrGpu::makeCopyForTextureParams(int width, int height, const GrTextureParams& textureParams,
bsalomon89fe56b2015-10-29 10:49:28 -070059 GrTextureProducer::CopyParams* copyParams) const {
bsalomon045802d2015-10-20 07:58:01 -070060 const GrCaps& caps = *this->caps();
61 if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
62 (!SkIsPow2(width) || !SkIsPow2(height))) {
bsalomon100b8f82015-10-28 08:37:44 -070063 copyParams->fWidth = GrNextPow2(width);
64 copyParams->fHeight = GrNextPow2(height);
bsalomon045802d2015-10-20 07:58:01 -070065 switch (textureParams.filterMode()) {
66 case GrTextureParams::kNone_FilterMode:
67 copyParams->fFilter = GrTextureParams::kNone_FilterMode;
68 break;
69 case GrTextureParams::kBilerp_FilterMode:
70 case GrTextureParams::kMipMap_FilterMode:
71 // We are only ever scaling up so no reason to ever indicate kMipMap.
72 copyParams->fFilter = GrTextureParams::kBilerp_FilterMode;
73 break;
74 }
bsalomon100b8f82015-10-28 08:37:44 -070075 return true;
bsalomon045802d2015-10-20 07:58:01 -070076 }
bsalomon100b8f82015-10-28 08:37:44 -070077 return false;
bsalomon045802d2015-10-20 07:58:01 -070078}
79
egdanielcf614fd2015-04-22 13:58:58 -070080static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
egdanielb0e1be22015-04-22 13:27:39 -070081 // By default, GrRenderTargets are GL's normal orientation so that they
82 // can be drawn to by the outside world without the client having
83 // to render upside down.
84 if (kDefault_GrSurfaceOrigin == origin) {
85 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
86 } else {
87 return origin;
88 }
89}
90
cblume55f2d2d2016-02-26 13:20:48 -080091/**
92 * Prior to creating a texture, make sure the type of texture being created is
93 * supported by calling check_texture_creation_params.
94 *
95 * @param caps The capabilities of the GL device.
96 * @param desc The descriptor of the texture to create.
97 * @param isRT Indicates if the texture can be a render target.
98 */
99static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
bsalomone699d0c2016-03-09 06:25:15 -0800100 bool* isRT, const SkTArray<GrMipLevel>& texels) {
cblume55f2d2d2016-02-26 13:20:48 -0800101 if (!caps.isConfigTexturable(desc.fConfig)) {
102 return false;
robertphillips@google.comd3eb3362012-10-31 13:56:35 +0000103 }
krajcevski9c0e6292014-06-02 07:38:14 -0700104
cblume55f2d2d2016-02-26 13:20:48 -0800105 *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
106 if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
107 return false;
commit-bot@chromium.org6b7938f2013-10-15 14:18:16 +0000108 }
robertphillips@google.comd3eb3362012-10-31 13:56:35 +0000109
robertphillips6e83ac72015-08-13 05:19:14 -0700110 // We currently do not support multisampled textures
cblume55f2d2d2016-02-26 13:20:48 -0800111 if (!*isRT && desc.fSampleCnt > 0) {
112 return false;
113 }
114
115 if (*isRT) {
116 int maxRTSize = caps.maxRenderTargetSize();
117 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
118 return false;
119 }
120 } else {
121 int maxSize = caps.maxTextureSize();
122 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
123 return false;
124 }
125 }
bsalomone699d0c2016-03-09 06:25:15 -0800126
127 for (int i = 0; i < texels.count(); ++i) {
128 if (!texels[i].fPixels) {
129 return false;
130 }
131 }
cblume55f2d2d2016-02-26 13:20:48 -0800132 return true;
133}
134
135GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
136 const SkTArray<GrMipLevel>& texels) {
137 GrSurfaceDesc desc = origDesc;
138
139 const GrCaps* caps = this->caps();
140 bool isRT = false;
bsalomone699d0c2016-03-09 06:25:15 -0800141 bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT, texels);
cblume55f2d2d2016-02-26 13:20:48 -0800142 if (!textureCreationParamsValid) {
halcanary96fcdcc2015-08-27 07:41:13 -0700143 return nullptr;
egdaniel8c9b6f12015-05-12 13:36:30 -0700144 }
145
cblume55f2d2d2016-02-26 13:20:48 -0800146 desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
147 // Attempt to catch un- or wrongly intialized sample counts;
egdanielb0e1be22015-04-22 13:27:39 -0700148 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
149
150 desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
151
cblume55f2d2d2016-02-26 13:20:48 -0800152 GrTexture* tex = nullptr;
153 GrGpuResource::LifeCycle lifeCycle = SkBudgeted::kYes == budgeted ?
154 GrGpuResource::kCached_LifeCycle :
155 GrGpuResource::kUncached_LifeCycle;
156
krajcevski9c0e6292014-06-02 07:38:14 -0700157 if (GrPixelConfigIsCompressed(desc.fConfig)) {
158 // We shouldn't be rendering into this
egdanielb0e1be22015-04-22 13:27:39 -0700159 SkASSERT(!isRT);
160 SkASSERT(0 == desc.fSampleCnt);
krajcevski9c0e6292014-06-02 07:38:14 -0700161
cblume55f2d2d2016-02-26 13:20:48 -0800162 if (!caps->npotTextureTileSupport() &&
tfarinaf9dae782014-06-06 06:35:28 -0700163 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
halcanary96fcdcc2015-08-27 07:41:13 -0700164 return nullptr;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000165 }
tfarinaf9dae782014-06-06 06:35:28 -0700166
krajcevski9c0e6292014-06-02 07:38:14 -0700167 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800168 tex = this->onCreateCompressedTexture(desc, lifeCycle, texels);
krajcevski9c0e6292014-06-02 07:38:14 -0700169 } else {
170 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800171 tex = this->onCreateTexture(desc, lifeCycle, texels);
bsalomondb558dd2015-01-23 13:19:00 -0800172 }
bsalomonb12ea412015-02-02 21:19:50 -0800173 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800174 if (!caps->reuseScratchTextures() && !isRT) {
175 tex->resourcePriv().removeScratchKey();
176 }
bsalomonb12ea412015-02-02 21:19:50 -0800177 fStats.incTextureCreates();
cblume55f2d2d2016-02-26 13:20:48 -0800178 if (!texels.empty()) {
179 if (texels[0].fPixels) {
180 fStats.incTextureUploads();
181 }
bsalomonb12ea412015-02-02 21:19:50 -0800182 }
183 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000184 return tex;
185}
186
bsalomon6dc6f5f2015-06-18 09:12:16 -0700187GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000188 this->handleDirtyContext();
bsalomon5b30c6f2015-12-17 14:17:34 -0800189 if (!this->caps()->isConfigTexturable(desc.fConfig)) {
190 return nullptr;
191 }
192 if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) &&
193 !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
194 return nullptr;
195 }
ericrkf7b8b8a2016-02-24 14:49:51 -0800196 int maxSize = this->caps()->maxTextureSize();
197 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
198 return nullptr;
199 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700200 GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
halcanary96fcdcc2015-08-27 07:41:13 -0700201 if (nullptr == tex) {
202 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000203 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000204 // TODO: defer this and attach dynamically
205 GrRenderTarget* tgt = tex->asRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700206 if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000207 tex->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700208 return nullptr;
bsalomon@google.come269f212011-11-07 13:29:52 +0000209 } else {
210 return tex;
211 }
212}
213
bsalomon6dc6f5f2015-06-18 09:12:16 -0700214GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
215 GrWrapOwnership ownership) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800216 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
217 return nullptr;
218 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000219 this->handleDirtyContext();
bsalomon6dc6f5f2015-06-18 09:12:16 -0700220 return this->onWrapBackendRenderTarget(desc, ownership);
bsalomon@google.come269f212011-11-07 13:29:52 +0000221}
222
kkinnunen49c4c222016-04-01 04:50:37 -0700223GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800224 this->handleDirtyContext();
225 if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
226 return nullptr;
227 }
228 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
229 return nullptr;
230 }
231 int maxSize = this->caps()->maxTextureSize();
232 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
233 return nullptr;
234 }
kkinnunen49c4c222016-04-01 04:50:37 -0700235 return this->onWrapBackendTextureAsRenderTarget(desc);
ericrkf7b8b8a2016-02-24 14:49:51 -0800236}
237
cdalton397536c2016-03-25 12:15:03 -0700238GrBuffer* GrGpu::createBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000239 this->handleDirtyContext();
cdalton397536c2016-03-25 12:15:03 -0700240 GrBuffer* buffer = this->onCreateBuffer(type, size, accessPattern);
robertphillips1b8e1b52015-06-24 06:54:10 -0700241 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700242 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700243 }
cdalton397536c2016-03-25 12:15:03 -0700244 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800245}
246
egdaniel51c8d402015-08-06 10:54:13 -0700247void GrGpu::clear(const SkIRect& rect,
joshualitt3322fa42014-11-07 08:48:51 -0800248 GrColor color,
joshualitt3322fa42014-11-07 08:48:51 -0800249 GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800250 SkASSERT(renderTarget);
egdaniel51c8d402015-08-06 10:54:13 -0700251 SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000252 this->handleDirtyContext();
egdaniel51c8d402015-08-06 10:54:13 -0700253 this->onClear(renderTarget, rect, color);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000254}
255
joshualitt6db519c2014-10-29 08:48:18 -0700256void GrGpu::clearStencilClip(const SkIRect& rect,
257 bool insideClip,
258 GrRenderTarget* renderTarget) {
joshualittd53a8272014-11-10 16:03:14 -0800259 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700260 this->handleDirtyContext();
261 this->onClearStencilClip(renderTarget, rect, insideClip);
262}
263
joshualitt1cbdcde2015-08-21 11:53:29 -0700264bool GrGpu::copySurface(GrSurface* dst,
265 GrSurface* src,
266 const SkIRect& srcRect,
267 const SkIPoint& dstPoint) {
268 SkASSERT(dst && src);
269 this->handleDirtyContext();
270 return this->onCopySurface(dst, src, srcRect, dstPoint);
271}
272
bsalomonf0674512015-07-28 13:26:15 -0700273bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
274 GrPixelConfig readConfig, DrawPreference* drawPreference,
275 ReadPixelTempDrawInfo* tempDrawInfo) {
276 SkASSERT(drawPreference);
277 SkASSERT(tempDrawInfo);
278 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
279
egdaniel6d901da2015-07-30 12:02:15 -0700280 // We currently do not support reading into a compressed buffer
281 if (GrPixelConfigIsCompressed(readConfig)) {
282 return false;
283 }
284
bsalomonf0674512015-07-28 13:26:15 -0700285 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
286 tempDrawInfo)) {
287 return false;
288 }
289
290 // Check to see if we're going to request that the caller draw when drawing is not possible.
291 if (!srcSurface->asTexture() ||
292 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
293 // If we don't have a fallback to a straight read then fail.
294 if (kRequireDraw_DrawPreference == *drawPreference) {
295 return false;
296 }
297 *drawPreference = kNoDraw_DrawPreference;
298 }
299
300 return true;
301}
cblumeed828002016-02-16 13:00:01 -0800302bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700303 GrPixelConfig srcConfig, DrawPreference* drawPreference,
304 WritePixelTempDrawInfo* tempDrawInfo) {
305 SkASSERT(drawPreference);
306 SkASSERT(tempDrawInfo);
307 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
308
jvanverth2dc29942015-09-01 07:16:46 -0700309 if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
310 dstSurface->desc().fConfig != srcConfig) {
311 return false;
312 }
313
bsalomonbabafcc2016-02-16 11:36:47 -0800314 if (SkToBool(dstSurface->asRenderTarget())) {
315 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
316 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
317 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
318 (width < dstSurface->width() || height < dstSurface->height())) {
319 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
320 }
bsalomonf0674512015-07-28 13:26:15 -0700321 }
322
cblumeed828002016-02-16 13:00:01 -0800323 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700324 tempDrawInfo)) {
325 return false;
326 }
327
328 // Check to see if we're going to request that the caller draw when drawing is not possible.
329 if (!dstSurface->asRenderTarget() ||
330 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
331 // If we don't have a fallback to a straight upload then fail.
332 if (kRequireDraw_DrawPreference == *drawPreference ||
333 !this->caps()->isConfigTexturable(srcConfig)) {
334 return false;
335 }
336 *drawPreference = kNoDraw_DrawPreference;
337 }
338 return true;
339}
340
bsalomon6cb3cbe2015-07-30 07:34:27 -0700341bool GrGpu::readPixels(GrSurface* surface,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000342 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000343 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000344 size_t rowBytes) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000345 this->handleDirtyContext();
egdaniel6d901da2015-07-30 12:02:15 -0700346
347 // We cannot read pixels into a compressed buffer
348 if (GrPixelConfigIsCompressed(config)) {
349 return false;
350 }
351
352 size_t bpp = GrBytesPerPixel(config);
353 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
354 &left, &top, &width, &height,
355 &buffer,
356 &rowBytes)) {
357 return false;
358 }
359
360 return this->onReadPixels(surface,
361 left, top, width, height,
362 config, buffer,
363 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000364}
365
bsalomon6cb3cbe2015-07-30 07:34:27 -0700366bool GrGpu::writePixels(GrSurface* surface,
367 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800368 GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
369 if (!surface) {
370 return false;
371 }
cblume55f2d2d2016-02-26 13:20:48 -0800372 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800373 if (!texels[currentMipLevel].fPixels ) {
374 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800375 }
376 }
jvanverth2dc29942015-09-01 07:16:46 -0700377
bsalomon@google.com6f379512011-11-16 20:36:03 +0000378 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800379 if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
bsalomonb12ea412015-02-02 21:19:50 -0800380 fStats.incTextureUploads();
381 return true;
382 }
383 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000384}
385
cblume55f2d2d2016-02-26 13:20:48 -0800386bool GrGpu::writePixels(GrSurface* surface,
387 int left, int top, int width, int height,
388 GrPixelConfig config, const void* buffer,
389 size_t rowBytes) {
390 GrMipLevel mipLevel;
391 mipLevel.fPixels = buffer;
392 mipLevel.fRowBytes = rowBytes;
393 SkSTArray<1, GrMipLevel> texels;
394 texels.push_back(mipLevel);
395
396 return this->writePixels(surface, left, top, width, height, config, texels);
397}
398
jvanverth17aa0472016-01-05 10:41:27 -0800399bool GrGpu::transferPixels(GrSurface* surface,
400 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700401 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth17aa0472016-01-05 10:41:27 -0800402 size_t offset, size_t rowBytes) {
cdalton397536c2016-03-25 12:15:03 -0700403 SkASSERT(transferBuffer);
jvanverth17aa0472016-01-05 10:41:27 -0800404
405 this->handleDirtyContext();
cblume61214052016-01-26 09:10:48 -0800406 if (this->onTransferPixels(surface, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700407 transferBuffer, offset, rowBytes)) {
jvanverth17aa0472016-01-05 10:41:27 -0800408 fStats.incTransfersToTexture();
409 return true;
410 }
411 return false;
412}
413
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000414void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000415 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000416 this->handleDirtyContext();
417 this->onResolveRenderTarget(target);
418}
419
cdalton28f45b92016-03-07 13:58:26 -0800420inline static uint8_t multisample_specs_id(uint8_t numSamples, GrSurfaceOrigin origin,
421 const GrCaps& caps) {
422 if (!caps.sampleLocationsSupport()) {
423 return numSamples;
424 }
425
426 SkASSERT(numSamples < 128);
427 SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
428 return (numSamples << 1) | (origin - 1);
429
430 GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
431 GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
432}
433
434const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt,
435 const GrStencilSettings& stencil) {
436 const GrSurfaceDesc& desc = rt->desc();
437 uint8_t surfDescKey = multisample_specs_id(desc.fSampleCnt, desc.fOrigin, *this->caps());
438 if (fMultisampleSpecsMap.count() > surfDescKey && fMultisampleSpecsMap[surfDescKey]) {
439#if !defined(SK_DEBUG)
440 // In debug mode we query the multisample info every time and verify the caching is correct.
441 return *fMultisampleSpecsMap[surfDescKey];
442#endif
443 }
444 int effectiveSampleCnt;
445 SkAutoTDeleteArray<SkPoint> locations(nullptr);
446 this->onGetMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &locations);
447 SkASSERT(effectiveSampleCnt && effectiveSampleCnt >= desc.fSampleCnt);
448 uint8_t effectiveKey = multisample_specs_id(effectiveSampleCnt, desc.fOrigin, *this->caps());
449 if (fMultisampleSpecsMap.count() > effectiveKey && fMultisampleSpecsMap[effectiveKey]) {
450 const MultisampleSpecs& specs = *fMultisampleSpecsMap[effectiveKey];
451 SkASSERT(effectiveKey == specs.fUniqueID);
452 SkASSERT(effectiveSampleCnt == specs.fEffectiveSampleCnt);
453 SkASSERT(!this->caps()->sampleLocationsSupport() ||
454 !memcmp(locations.get(), specs.fSampleLocations.get(),
455 effectiveSampleCnt * sizeof(SkPoint)));
456 SkASSERT(surfDescKey <= effectiveKey);
457 SkASSERT(!fMultisampleSpecsMap[surfDescKey] || fMultisampleSpecsMap[surfDescKey] == &specs);
458 fMultisampleSpecsMap[surfDescKey] = &specs;
459 return specs;
460 }
461 const MultisampleSpecs& specs = *new (&fMultisampleSpecsAllocator)
mtklein18300a32016-03-16 13:53:35 -0700462 MultisampleSpecs{effectiveKey, effectiveSampleCnt, locations.release()};
cdalton28f45b92016-03-07 13:58:26 -0800463 if (fMultisampleSpecsMap.count() <= effectiveKey) {
464 int n = 1 + effectiveKey - fMultisampleSpecsMap.count();
465 fMultisampleSpecsMap.push_back_n(n, (const MultisampleSpecs*) nullptr);
466 }
467 fMultisampleSpecsMap[effectiveKey] = &specs;
468 if (effectiveSampleCnt != desc.fSampleCnt) {
469 SkASSERT(surfDescKey < effectiveKey);
470 fMultisampleSpecsMap[surfDescKey] = &specs;
471 }
472 return specs;
473}
474
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000475////////////////////////////////////////////////////////////////////////////////
476
bsalomon7dbd45d2016-03-23 10:40:53 -0700477bool GrGpu::draw(const GrPipeline& pipeline,
egdaniel0e1853c2016-03-17 11:35:45 -0700478 const GrPrimitiveProcessor& primProc,
479 const GrMesh* meshes,
480 int meshCount) {
bsalomon7dbd45d2016-03-23 10:40:53 -0700481 if (primProc.numAttribs() > this->caps()->maxVertexAttributes()) {
bsalomon1d417a82016-03-23 11:50:26 -0700482 fStats.incNumFailedDraws();
bsalomon7dbd45d2016-03-23 10:40:53 -0700483 return false;
484 }
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000485 this->handleDirtyContext();
bsalomoncb02b382015-08-12 11:14:50 -0700486
egdaniel0e1853c2016-03-17 11:35:45 -0700487 this->onDraw(pipeline, primProc, meshes, meshCount);
bsalomon7dbd45d2016-03-23 10:40:53 -0700488 return true;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000489}