blob: d062a48129df89d09a5b4b4c016d58c0e64fd52a [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
cdaltone2e71c22016-04-07 18:13:29 -0700238GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700239 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000240 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700241 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700242 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700243 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700244 }
cdalton397536c2016-03-25 12:15:03 -0700245 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800246}
247
egdaniel51c8d402015-08-06 10:54:13 -0700248void GrGpu::clear(const SkIRect& rect,
joshualitt3322fa42014-11-07 08:48:51 -0800249 GrColor color,
joshualitt3322fa42014-11-07 08:48:51 -0800250 GrRenderTarget* renderTarget) {
bsalomon89c62982014-11-03 12:08:42 -0800251 SkASSERT(renderTarget);
egdaniel51c8d402015-08-06 10:54:13 -0700252 SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000253 this->handleDirtyContext();
egdaniel51c8d402015-08-06 10:54:13 -0700254 this->onClear(renderTarget, rect, color);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000255}
256
joshualitt6db519c2014-10-29 08:48:18 -0700257void GrGpu::clearStencilClip(const SkIRect& rect,
258 bool insideClip,
259 GrRenderTarget* renderTarget) {
joshualittd53a8272014-11-10 16:03:14 -0800260 SkASSERT(renderTarget);
joshualitt6db519c2014-10-29 08:48:18 -0700261 this->handleDirtyContext();
262 this->onClearStencilClip(renderTarget, rect, insideClip);
263}
264
joshualitt1cbdcde2015-08-21 11:53:29 -0700265bool GrGpu::copySurface(GrSurface* dst,
266 GrSurface* src,
267 const SkIRect& srcRect,
268 const SkIPoint& dstPoint) {
269 SkASSERT(dst && src);
270 this->handleDirtyContext();
271 return this->onCopySurface(dst, src, srcRect, dstPoint);
272}
273
bsalomonf0674512015-07-28 13:26:15 -0700274bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
275 GrPixelConfig readConfig, DrawPreference* drawPreference,
276 ReadPixelTempDrawInfo* tempDrawInfo) {
277 SkASSERT(drawPreference);
278 SkASSERT(tempDrawInfo);
279 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
280
egdaniel6d901da2015-07-30 12:02:15 -0700281 // We currently do not support reading into a compressed buffer
282 if (GrPixelConfigIsCompressed(readConfig)) {
283 return false;
284 }
285
bsalomonf0674512015-07-28 13:26:15 -0700286 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
287 tempDrawInfo)) {
288 return false;
289 }
290
291 // Check to see if we're going to request that the caller draw when drawing is not possible.
292 if (!srcSurface->asTexture() ||
293 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
294 // If we don't have a fallback to a straight read then fail.
295 if (kRequireDraw_DrawPreference == *drawPreference) {
296 return false;
297 }
298 *drawPreference = kNoDraw_DrawPreference;
299 }
300
301 return true;
302}
cblumeed828002016-02-16 13:00:01 -0800303bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700304 GrPixelConfig srcConfig, DrawPreference* drawPreference,
305 WritePixelTempDrawInfo* tempDrawInfo) {
306 SkASSERT(drawPreference);
307 SkASSERT(tempDrawInfo);
308 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
309
jvanverth2dc29942015-09-01 07:16:46 -0700310 if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
311 dstSurface->desc().fConfig != srcConfig) {
312 return false;
313 }
314
bsalomonbabafcc2016-02-16 11:36:47 -0800315 if (SkToBool(dstSurface->asRenderTarget())) {
316 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
317 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
318 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
319 (width < dstSurface->width() || height < dstSurface->height())) {
320 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
321 }
bsalomonf0674512015-07-28 13:26:15 -0700322 }
323
cblumeed828002016-02-16 13:00:01 -0800324 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700325 tempDrawInfo)) {
326 return false;
327 }
328
329 // Check to see if we're going to request that the caller draw when drawing is not possible.
330 if (!dstSurface->asRenderTarget() ||
331 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
332 // If we don't have a fallback to a straight upload then fail.
333 if (kRequireDraw_DrawPreference == *drawPreference ||
334 !this->caps()->isConfigTexturable(srcConfig)) {
335 return false;
336 }
337 *drawPreference = kNoDraw_DrawPreference;
338 }
339 return true;
340}
341
bsalomon6cb3cbe2015-07-30 07:34:27 -0700342bool GrGpu::readPixels(GrSurface* surface,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000343 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000344 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000345 size_t rowBytes) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000346 this->handleDirtyContext();
egdaniel6d901da2015-07-30 12:02:15 -0700347
348 // We cannot read pixels into a compressed buffer
349 if (GrPixelConfigIsCompressed(config)) {
350 return false;
351 }
352
353 size_t bpp = GrBytesPerPixel(config);
354 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
355 &left, &top, &width, &height,
356 &buffer,
357 &rowBytes)) {
358 return false;
359 }
360
361 return this->onReadPixels(surface,
362 left, top, width, height,
363 config, buffer,
364 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000365}
366
bsalomon6cb3cbe2015-07-30 07:34:27 -0700367bool GrGpu::writePixels(GrSurface* surface,
368 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800369 GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
370 if (!surface) {
371 return false;
372 }
cblume55f2d2d2016-02-26 13:20:48 -0800373 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800374 if (!texels[currentMipLevel].fPixels ) {
375 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800376 }
377 }
jvanverth2dc29942015-09-01 07:16:46 -0700378
bsalomon@google.com6f379512011-11-16 20:36:03 +0000379 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800380 if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
bsalomonb12ea412015-02-02 21:19:50 -0800381 fStats.incTextureUploads();
382 return true;
383 }
384 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000385}
386
cblume55f2d2d2016-02-26 13:20:48 -0800387bool GrGpu::writePixels(GrSurface* surface,
388 int left, int top, int width, int height,
389 GrPixelConfig config, const void* buffer,
390 size_t rowBytes) {
391 GrMipLevel mipLevel;
392 mipLevel.fPixels = buffer;
393 mipLevel.fRowBytes = rowBytes;
394 SkSTArray<1, GrMipLevel> texels;
395 texels.push_back(mipLevel);
396
397 return this->writePixels(surface, left, top, width, height, config, texels);
398}
399
jvanverthc3d706f2016-04-20 10:33:27 -0700400bool GrGpu::transferPixels(GrSurface* surface,
jvanverth17aa0472016-01-05 10:41:27 -0800401 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700402 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth17aa0472016-01-05 10:41:27 -0800403 size_t offset, size_t rowBytes) {
cdalton397536c2016-03-25 12:15:03 -0700404 SkASSERT(transferBuffer);
jvanverth17aa0472016-01-05 10:41:27 -0800405
406 this->handleDirtyContext();
jvanverthc3d706f2016-04-20 10:33:27 -0700407 if (this->onTransferPixels(surface, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700408 transferBuffer, offset, rowBytes)) {
jvanverth17aa0472016-01-05 10:41:27 -0800409 fStats.incTransfersToTexture();
410 return true;
411 }
412 return false;
413}
414
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000415void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000416 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000417 this->handleDirtyContext();
418 this->onResolveRenderTarget(target);
419}
420
cdalton28f45b92016-03-07 13:58:26 -0800421inline static uint8_t multisample_specs_id(uint8_t numSamples, GrSurfaceOrigin origin,
422 const GrCaps& caps) {
423 if (!caps.sampleLocationsSupport()) {
424 return numSamples;
425 }
426
427 SkASSERT(numSamples < 128);
428 SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
429 return (numSamples << 1) | (origin - 1);
430
431 GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin);
432 GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin);
433}
434
435const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt,
436 const GrStencilSettings& stencil) {
437 const GrSurfaceDesc& desc = rt->desc();
438 uint8_t surfDescKey = multisample_specs_id(desc.fSampleCnt, desc.fOrigin, *this->caps());
439 if (fMultisampleSpecsMap.count() > surfDescKey && fMultisampleSpecsMap[surfDescKey]) {
440#if !defined(SK_DEBUG)
441 // In debug mode we query the multisample info every time and verify the caching is correct.
442 return *fMultisampleSpecsMap[surfDescKey];
443#endif
444 }
445 int effectiveSampleCnt;
446 SkAutoTDeleteArray<SkPoint> locations(nullptr);
447 this->onGetMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &locations);
448 SkASSERT(effectiveSampleCnt && effectiveSampleCnt >= desc.fSampleCnt);
449 uint8_t effectiveKey = multisample_specs_id(effectiveSampleCnt, desc.fOrigin, *this->caps());
450 if (fMultisampleSpecsMap.count() > effectiveKey && fMultisampleSpecsMap[effectiveKey]) {
451 const MultisampleSpecs& specs = *fMultisampleSpecsMap[effectiveKey];
452 SkASSERT(effectiveKey == specs.fUniqueID);
453 SkASSERT(effectiveSampleCnt == specs.fEffectiveSampleCnt);
454 SkASSERT(!this->caps()->sampleLocationsSupport() ||
455 !memcmp(locations.get(), specs.fSampleLocations.get(),
456 effectiveSampleCnt * sizeof(SkPoint)));
457 SkASSERT(surfDescKey <= effectiveKey);
458 SkASSERT(!fMultisampleSpecsMap[surfDescKey] || fMultisampleSpecsMap[surfDescKey] == &specs);
459 fMultisampleSpecsMap[surfDescKey] = &specs;
460 return specs;
461 }
462 const MultisampleSpecs& specs = *new (&fMultisampleSpecsAllocator)
mtklein18300a32016-03-16 13:53:35 -0700463 MultisampleSpecs{effectiveKey, effectiveSampleCnt, locations.release()};
cdalton28f45b92016-03-07 13:58:26 -0800464 if (fMultisampleSpecsMap.count() <= effectiveKey) {
465 int n = 1 + effectiveKey - fMultisampleSpecsMap.count();
466 fMultisampleSpecsMap.push_back_n(n, (const MultisampleSpecs*) nullptr);
467 }
468 fMultisampleSpecsMap[effectiveKey] = &specs;
469 if (effectiveSampleCnt != desc.fSampleCnt) {
470 SkASSERT(surfDescKey < effectiveKey);
471 fMultisampleSpecsMap[surfDescKey] = &specs;
472 }
473 return specs;
474}
475
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000476////////////////////////////////////////////////////////////////////////////////
477
bsalomon7dbd45d2016-03-23 10:40:53 -0700478bool GrGpu::draw(const GrPipeline& pipeline,
egdaniel0e1853c2016-03-17 11:35:45 -0700479 const GrPrimitiveProcessor& primProc,
480 const GrMesh* meshes,
481 int meshCount) {
bsalomon7dbd45d2016-03-23 10:40:53 -0700482 if (primProc.numAttribs() > this->caps()->maxVertexAttributes()) {
bsalomon1d417a82016-03-23 11:50:26 -0700483 fStats.incNumFailedDraws();
bsalomon7dbd45d2016-03-23 10:40:53 -0700484 return false;
485 }
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000486 this->handleDirtyContext();
bsalomoncb02b382015-08-12 11:14:50 -0700487
egdaniel0e1853c2016-03-17 11:35:45 -0700488 this->onDraw(pipeline, primProc, meshes, meshCount);
bsalomon7dbd45d2016-03-23 10:40:53 -0700489 return true;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000490}