blob: eef7118a1b290aea3eccc3131fa3f4c67f14254d [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;
cblume55f2d2d2016-02-26 13:20:48 -0800153
krajcevski9c0e6292014-06-02 07:38:14 -0700154 if (GrPixelConfigIsCompressed(desc.fConfig)) {
155 // We shouldn't be rendering into this
egdanielb0e1be22015-04-22 13:27:39 -0700156 SkASSERT(!isRT);
157 SkASSERT(0 == desc.fSampleCnt);
krajcevski9c0e6292014-06-02 07:38:14 -0700158
cblume55f2d2d2016-02-26 13:20:48 -0800159 if (!caps->npotTextureTileSupport() &&
tfarinaf9dae782014-06-06 06:35:28 -0700160 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
halcanary96fcdcc2015-08-27 07:41:13 -0700161 return nullptr;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000162 }
tfarinaf9dae782014-06-06 06:35:28 -0700163
krajcevski9c0e6292014-06-02 07:38:14 -0700164 this->handleDirtyContext();
kkinnunen2e6055b2016-04-22 01:48:29 -0700165 tex = this->onCreateCompressedTexture(desc, budgeted, texels);
krajcevski9c0e6292014-06-02 07:38:14 -0700166 } else {
167 this->handleDirtyContext();
kkinnunen2e6055b2016-04-22 01:48:29 -0700168 tex = this->onCreateTexture(desc, budgeted, texels);
bsalomondb558dd2015-01-23 13:19:00 -0800169 }
bsalomonb12ea412015-02-02 21:19:50 -0800170 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800171 if (!caps->reuseScratchTextures() && !isRT) {
172 tex->resourcePriv().removeScratchKey();
173 }
bsalomonb12ea412015-02-02 21:19:50 -0800174 fStats.incTextureCreates();
cblume55f2d2d2016-02-26 13:20:48 -0800175 if (!texels.empty()) {
176 if (texels[0].fPixels) {
177 fStats.incTextureUploads();
178 }
bsalomonb12ea412015-02-02 21:19:50 -0800179 }
180 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000181 return tex;
182}
183
bsalomon6dc6f5f2015-06-18 09:12:16 -0700184GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000185 this->handleDirtyContext();
bsalomon5b30c6f2015-12-17 14:17:34 -0800186 if (!this->caps()->isConfigTexturable(desc.fConfig)) {
187 return nullptr;
188 }
189 if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) &&
190 !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
191 return nullptr;
192 }
ericrkf7b8b8a2016-02-24 14:49:51 -0800193 int maxSize = this->caps()->maxTextureSize();
194 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
195 return nullptr;
196 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700197 GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
halcanary96fcdcc2015-08-27 07:41:13 -0700198 if (nullptr == tex) {
199 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000200 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000201 // TODO: defer this and attach dynamically
202 GrRenderTarget* tgt = tex->asRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700203 if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000204 tex->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700205 return nullptr;
bsalomon@google.come269f212011-11-07 13:29:52 +0000206 } else {
207 return tex;
208 }
209}
210
bsalomon6dc6f5f2015-06-18 09:12:16 -0700211GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
212 GrWrapOwnership ownership) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800213 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
214 return nullptr;
215 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000216 this->handleDirtyContext();
bsalomon6dc6f5f2015-06-18 09:12:16 -0700217 return this->onWrapBackendRenderTarget(desc, ownership);
bsalomon@google.come269f212011-11-07 13:29:52 +0000218}
219
kkinnunen49c4c222016-04-01 04:50:37 -0700220GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800221 this->handleDirtyContext();
222 if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
223 return nullptr;
224 }
225 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
226 return nullptr;
227 }
228 int maxSize = this->caps()->maxTextureSize();
229 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
230 return nullptr;
231 }
kkinnunen49c4c222016-04-01 04:50:37 -0700232 return this->onWrapBackendTextureAsRenderTarget(desc);
ericrkf7b8b8a2016-02-24 14:49:51 -0800233}
234
cdaltone2e71c22016-04-07 18:13:29 -0700235GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700236 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000237 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700238 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700239 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700240 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700241 }
cdalton397536c2016-03-25 12:15:03 -0700242 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800243}
244
egdaniel51c8d402015-08-06 10:54:13 -0700245void GrGpu::clear(const SkIRect& rect,
joshualitt3322fa42014-11-07 08:48:51 -0800246 GrColor color,
joshualitt3322fa42014-11-07 08:48:51 -0800247 GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800248 SkASSERT(renderTarget);
egdaniel51c8d402015-08-06 10:54:13 -0700249 SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000250 this->handleDirtyContext();
egdaniel51c8d402015-08-06 10:54:13 -0700251 this->onClear(renderTarget, rect, color);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000252}
253
joshualitt6db519c2014-10-29 08:48:18 -0700254void GrGpu::clearStencilClip(const SkIRect& rect,
255 bool insideClip,
256 GrRenderTarget* renderTarget) {
joshualittd53a8272014-11-10 16:03:14 -0800257 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700258 this->handleDirtyContext();
259 this->onClearStencilClip(renderTarget, rect, insideClip);
260}
261
joshualitt1cbdcde2015-08-21 11:53:29 -0700262bool GrGpu::copySurface(GrSurface* dst,
263 GrSurface* src,
264 const SkIRect& srcRect,
265 const SkIPoint& dstPoint) {
266 SkASSERT(dst && src);
267 this->handleDirtyContext();
268 return this->onCopySurface(dst, src, srcRect, dstPoint);
269}
270
bsalomonf0674512015-07-28 13:26:15 -0700271bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
272 GrPixelConfig readConfig, DrawPreference* drawPreference,
273 ReadPixelTempDrawInfo* tempDrawInfo) {
274 SkASSERT(drawPreference);
275 SkASSERT(tempDrawInfo);
276 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
277
egdaniel6d901da2015-07-30 12:02:15 -0700278 // We currently do not support reading into a compressed buffer
279 if (GrPixelConfigIsCompressed(readConfig)) {
280 return false;
281 }
282
bsalomonf0674512015-07-28 13:26:15 -0700283 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
284 tempDrawInfo)) {
285 return false;
286 }
287
288 // Check to see if we're going to request that the caller draw when drawing is not possible.
289 if (!srcSurface->asTexture() ||
290 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
291 // If we don't have a fallback to a straight read then fail.
292 if (kRequireDraw_DrawPreference == *drawPreference) {
293 return false;
294 }
295 *drawPreference = kNoDraw_DrawPreference;
296 }
297
298 return true;
299}
cblumeed828002016-02-16 13:00:01 -0800300bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700301 GrPixelConfig srcConfig, DrawPreference* drawPreference,
302 WritePixelTempDrawInfo* tempDrawInfo) {
303 SkASSERT(drawPreference);
304 SkASSERT(tempDrawInfo);
305 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
306
jvanverth2dc29942015-09-01 07:16:46 -0700307 if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
308 dstSurface->desc().fConfig != srcConfig) {
309 return false;
310 }
311
bsalomonbabafcc2016-02-16 11:36:47 -0800312 if (SkToBool(dstSurface->asRenderTarget())) {
313 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
314 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
315 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
316 (width < dstSurface->width() || height < dstSurface->height())) {
317 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
318 }
bsalomonf0674512015-07-28 13:26:15 -0700319 }
320
cblumeed828002016-02-16 13:00:01 -0800321 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700322 tempDrawInfo)) {
323 return false;
324 }
325
326 // Check to see if we're going to request that the caller draw when drawing is not possible.
327 if (!dstSurface->asRenderTarget() ||
328 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
329 // If we don't have a fallback to a straight upload then fail.
330 if (kRequireDraw_DrawPreference == *drawPreference ||
331 !this->caps()->isConfigTexturable(srcConfig)) {
332 return false;
333 }
334 *drawPreference = kNoDraw_DrawPreference;
335 }
336 return true;
337}
338
bsalomon6cb3cbe2015-07-30 07:34:27 -0700339bool GrGpu::readPixels(GrSurface* surface,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000340 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000341 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000342 size_t rowBytes) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000343 this->handleDirtyContext();
egdaniel6d901da2015-07-30 12:02:15 -0700344
345 // We cannot read pixels into a compressed buffer
346 if (GrPixelConfigIsCompressed(config)) {
347 return false;
348 }
349
350 size_t bpp = GrBytesPerPixel(config);
351 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
352 &left, &top, &width, &height,
353 &buffer,
354 &rowBytes)) {
355 return false;
356 }
357
358 return this->onReadPixels(surface,
359 left, top, width, height,
360 config, buffer,
361 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000362}
363
bsalomon6cb3cbe2015-07-30 07:34:27 -0700364bool GrGpu::writePixels(GrSurface* surface,
365 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800366 GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
367 if (!surface) {
368 return false;
369 }
cblume55f2d2d2016-02-26 13:20:48 -0800370 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800371 if (!texels[currentMipLevel].fPixels ) {
372 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800373 }
374 }
jvanverth2dc29942015-09-01 07:16:46 -0700375
bsalomon@google.com6f379512011-11-16 20:36:03 +0000376 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800377 if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
bsalomonb12ea412015-02-02 21:19:50 -0800378 fStats.incTextureUploads();
379 return true;
380 }
381 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000382}
383
cblume55f2d2d2016-02-26 13:20:48 -0800384bool GrGpu::writePixels(GrSurface* surface,
385 int left, int top, int width, int height,
386 GrPixelConfig config, const void* buffer,
387 size_t rowBytes) {
388 GrMipLevel mipLevel;
389 mipLevel.fPixels = buffer;
390 mipLevel.fRowBytes = rowBytes;
391 SkSTArray<1, GrMipLevel> texels;
392 texels.push_back(mipLevel);
393
394 return this->writePixels(surface, left, top, width, height, config, texels);
395}
396
jvanverthc3d706f2016-04-20 10:33:27 -0700397bool GrGpu::transferPixels(GrSurface* surface,
jvanverth17aa0472016-01-05 10:41:27 -0800398 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700399 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth17aa0472016-01-05 10:41:27 -0800400 size_t offset, size_t rowBytes) {
cdalton397536c2016-03-25 12:15:03 -0700401 SkASSERT(transferBuffer);
jvanverth17aa0472016-01-05 10:41:27 -0800402
403 this->handleDirtyContext();
jvanverthc3d706f2016-04-20 10:33:27 -0700404 if (this->onTransferPixels(surface, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700405 transferBuffer, offset, rowBytes)) {
jvanverth17aa0472016-01-05 10:41:27 -0800406 fStats.incTransfersToTexture();
407 return true;
408 }
409 return false;
410}
411
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000412void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000413 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000414 this->handleDirtyContext();
415 this->onResolveRenderTarget(target);
416}
417
cdalton28f45b92016-03-07 13:58:26 -0800418inline static uint8_t multisample_specs_id(uint8_t numSamples, GrSurfaceOrigin origin,
419 const GrCaps& caps) {
420 if (!caps.sampleLocationsSupport()) {
421 return numSamples;
422 }
423
424 SkASSERT(numSamples < 128);
425 SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
426 return (numSamples << 1) | (origin - 1);
427
428 GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
429 GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
430}
431
432const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt,
433 const GrStencilSettings& stencil) {
434 const GrSurfaceDesc& desc = rt->desc();
435 uint8_t surfDescKey = multisample_specs_id(desc.fSampleCnt, desc.fOrigin, *this->caps());
436 if (fMultisampleSpecsMap.count() > surfDescKey && fMultisampleSpecsMap[surfDescKey]) {
437#if !defined(SK_DEBUG)
438 // In debug mode we query the multisample info every time and verify the caching is correct.
439 return *fMultisampleSpecsMap[surfDescKey];
440#endif
441 }
442 int effectiveSampleCnt;
443 SkAutoTDeleteArray<SkPoint> locations(nullptr);
444 this->onGetMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &locations);
445 SkASSERT(effectiveSampleCnt && effectiveSampleCnt >= desc.fSampleCnt);
446 uint8_t effectiveKey = multisample_specs_id(effectiveSampleCnt, desc.fOrigin, *this->caps());
447 if (fMultisampleSpecsMap.count() > effectiveKey && fMultisampleSpecsMap[effectiveKey]) {
448 const MultisampleSpecs& specs = *fMultisampleSpecsMap[effectiveKey];
449 SkASSERT(effectiveKey == specs.fUniqueID);
450 SkASSERT(effectiveSampleCnt == specs.fEffectiveSampleCnt);
451 SkASSERT(!this->caps()->sampleLocationsSupport() ||
452 !memcmp(locations.get(), specs.fSampleLocations.get(),
453 effectiveSampleCnt * sizeof(SkPoint)));
454 SkASSERT(surfDescKey <= effectiveKey);
455 SkASSERT(!fMultisampleSpecsMap[surfDescKey] || fMultisampleSpecsMap[surfDescKey] == &specs);
456 fMultisampleSpecsMap[surfDescKey] = &specs;
457 return specs;
458 }
459 const MultisampleSpecs& specs = *new (&fMultisampleSpecsAllocator)
mtklein18300a32016-03-16 13:53:35 -0700460 MultisampleSpecs{effectiveKey, effectiveSampleCnt, locations.release()};
cdalton28f45b92016-03-07 13:58:26 -0800461 if (fMultisampleSpecsMap.count() <= effectiveKey) {
462 int n = 1 + effectiveKey - fMultisampleSpecsMap.count();
463 fMultisampleSpecsMap.push_back_n(n, (const MultisampleSpecs*) nullptr);
464 }
465 fMultisampleSpecsMap[effectiveKey] = &specs;
466 if (effectiveSampleCnt != desc.fSampleCnt) {
467 SkASSERT(surfDescKey < effectiveKey);
468 fMultisampleSpecsMap[surfDescKey] = &specs;
469 }
470 return specs;
471}
472
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000473////////////////////////////////////////////////////////////////////////////////
474
bsalomon7dbd45d2016-03-23 10:40:53 -0700475bool GrGpu::draw(const GrPipeline& pipeline,
egdaniel0e1853c2016-03-17 11:35:45 -0700476 const GrPrimitiveProcessor& primProc,
477 const GrMesh* meshes,
478 int meshCount) {
bsalomon7dbd45d2016-03-23 10:40:53 -0700479 if (primProc.numAttribs() > this->caps()->maxVertexAttributes()) {
bsalomon1d417a82016-03-23 11:50:26 -0700480 fStats.incNumFailedDraws();
bsalomon7dbd45d2016-03-23 10:40:53 -0700481 return false;
482 }
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000483 this->handleDirtyContext();
bsalomoncb02b382015-08-12 11:14:50 -0700484
egdaniel0e1853c2016-03-17 11:35:45 -0700485 this->onDraw(pipeline, primProc, meshes, meshCount);
bsalomon7dbd45d2016-03-23 10:40:53 -0700486 return true;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000487}