blob: 12a2d922819f62f87c8c69d2e12dcd1f7d9b7f15 [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
Greg Daniel7ef28f32017-04-20 16:41:55 +000011#include "GrBackendSurface.h"
cdalton397536c2016-03-25 12:15:03 -070012#include "GrBuffer.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070013#include "GrCaps.h"
bsalomon@google.com558a75b2011-08-08 17:01:14 +000014#include "GrContext.h"
bsalomon3582d3e2015-02-13 14:20:05 -080015#include "GrGpuResourcePriv.h"
egdaniel0e1853c2016-03-17 11:35:45 -070016#include "GrMesh.h"
kkinnunencabe20c2015-06-01 01:37:26 -070017#include "GrPathRendering.h"
bsalomoncb02b382015-08-12 11:14:50 -070018#include "GrPipeline.h"
bsalomon0ea80f42015-02-11 10:49:59 -080019#include "GrResourceCache.h"
egdanielec00d942015-09-14 12:56:10 -070020#include "GrResourceProvider.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080021#include "GrRenderTargetPriv.h"
egdaniel8dc7c3a2015-04-16 11:22:42 -070022#include "GrStencilAttachment.h"
csmartdaltonc633abb2016-11-01 08:55:55 -070023#include "GrStencilSettings.h"
egdaniel6d901da2015-07-30 12:02:15 -070024#include "GrSurfacePriv.h"
jvanverth900bd4a2016-04-29 13:53:12 -070025#include "GrTexturePriv.h"
halcanary4dbbd042016-06-07 17:21:10 -070026#include "SkMathPriv.h"
bsalomoncb8979d2015-05-05 09:51:38 -070027
bsalomon@google.comd302f142011-03-03 13:54:13 +000028////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000029
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000030GrGpu::GrGpu(GrContext* context)
joshualitt3322fa42014-11-07 08:48:51 -080031 : fResetTimestamp(kExpiredTimestamp+1)
bsalomon@google.com0a208a12013-06-28 18:57:35 +000032 , fResetBits(kAll_GrBackendState)
joshualitt3322fa42014-11-07 08:48:51 -080033 , fContext(context) {
csmartdalton0d28e572016-07-06 09:59:43 -070034 fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
reed@google.comac10a2d2010-12-22 21:39:39 +000035}
36
bsalomoned0bcad2015-05-04 10:36:42 -070037GrGpu::~GrGpu() {}
bsalomon1d89ddc2014-08-19 14:20:58 -070038
bsalomon6e2aad42016-04-01 11:54:31 -070039void GrGpu::disconnect(DisconnectType) {}
reed@google.comac10a2d2010-12-22 21:39:39 +000040
bsalomon@google.comd302f142011-03-03 13:54:13 +000041////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000042
Robert Phillips81444fb2017-03-21 09:14:35 -040043bool GrGpu::isACopyNeededForTextureParams(int width, int height,
44 const GrSamplerParams& textureParams,
45 GrTextureProducer::CopyParams* copyParams,
46 SkScalar scaleAdjust[2]) const {
bsalomon045802d2015-10-20 07:58:01 -070047 const GrCaps& caps = *this->caps();
48 if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
49 (!SkIsPow2(width) || !SkIsPow2(height))) {
Robert Phillips67c18d62017-01-20 12:44:06 -050050 SkASSERT(scaleAdjust);
bsalomon100b8f82015-10-28 08:37:44 -070051 copyParams->fWidth = GrNextPow2(width);
52 copyParams->fHeight = GrNextPow2(height);
Robert Phillips67c18d62017-01-20 12:44:06 -050053 scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
54 scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
bsalomon045802d2015-10-20 07:58:01 -070055 switch (textureParams.filterMode()) {
Brian Salomon514baff2016-11-17 15:17:07 -050056 case GrSamplerParams::kNone_FilterMode:
57 copyParams->fFilter = GrSamplerParams::kNone_FilterMode;
bsalomon045802d2015-10-20 07:58:01 -070058 break;
Brian Salomon514baff2016-11-17 15:17:07 -050059 case GrSamplerParams::kBilerp_FilterMode:
60 case GrSamplerParams::kMipMap_FilterMode:
bsalomon045802d2015-10-20 07:58:01 -070061 // We are only ever scaling up so no reason to ever indicate kMipMap.
Brian Salomon514baff2016-11-17 15:17:07 -050062 copyParams->fFilter = GrSamplerParams::kBilerp_FilterMode;
bsalomon045802d2015-10-20 07:58:01 -070063 break;
64 }
bsalomon100b8f82015-10-28 08:37:44 -070065 return true;
bsalomon045802d2015-10-20 07:58:01 -070066 }
bsalomon100b8f82015-10-28 08:37:44 -070067 return false;
bsalomon045802d2015-10-20 07:58:01 -070068}
69
egdanielcf614fd2015-04-22 13:58:58 -070070static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
egdanielb0e1be22015-04-22 13:27:39 -070071 // By default, GrRenderTargets are GL's normal orientation so that they
72 // can be drawn to by the outside world without the client having
73 // to render upside down.
74 if (kDefault_GrSurfaceOrigin == origin) {
75 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
76 } else {
77 return origin;
78 }
79}
80
cblume55f2d2d2016-02-26 13:20:48 -080081/**
82 * Prior to creating a texture, make sure the type of texture being created is
83 * supported by calling check_texture_creation_params.
84 *
85 * @param caps The capabilities of the GL device.
86 * @param desc The descriptor of the texture to create.
87 * @param isRT Indicates if the texture can be a render target.
88 */
89static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
bsalomone699d0c2016-03-09 06:25:15 -080090 bool* isRT, const SkTArray<GrMipLevel>& texels) {
cblume55f2d2d2016-02-26 13:20:48 -080091 if (!caps.isConfigTexturable(desc.fConfig)) {
92 return false;
robertphillips@google.comd3eb3362012-10-31 13:56:35 +000093 }
krajcevski9c0e6292014-06-02 07:38:14 -070094
Brian Salomonbf7b6202016-11-11 16:08:03 -050095 if (GrPixelConfigIsSint(desc.fConfig) && texels.count() > 1) {
96 return false;
97 }
98
cblume55f2d2d2016-02-26 13:20:48 -080099 *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
100 if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
101 return false;
commit-bot@chromium.org6b7938f2013-10-15 14:18:16 +0000102 }
robertphillips@google.comd3eb3362012-10-31 13:56:35 +0000103
robertphillips6e83ac72015-08-13 05:19:14 -0700104 // We currently do not support multisampled textures
cblume55f2d2d2016-02-26 13:20:48 -0800105 if (!*isRT && desc.fSampleCnt > 0) {
106 return false;
107 }
108
109 if (*isRT) {
110 int maxRTSize = caps.maxRenderTargetSize();
111 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
112 return false;
113 }
114 } else {
115 int maxSize = caps.maxTextureSize();
116 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
117 return false;
118 }
119 }
bsalomone699d0c2016-03-09 06:25:15 -0800120
121 for (int i = 0; i < texels.count(); ++i) {
122 if (!texels[i].fPixels) {
123 return false;
124 }
125 }
cblume55f2d2d2016-02-26 13:20:48 -0800126 return true;
127}
128
129GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
130 const SkTArray<GrMipLevel>& texels) {
131 GrSurfaceDesc desc = origDesc;
132
133 const GrCaps* caps = this->caps();
134 bool isRT = false;
bsalomone699d0c2016-03-09 06:25:15 -0800135 bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT, texels);
cblume55f2d2d2016-02-26 13:20:48 -0800136 if (!textureCreationParamsValid) {
halcanary96fcdcc2015-08-27 07:41:13 -0700137 return nullptr;
egdaniel8c9b6f12015-05-12 13:36:30 -0700138 }
139
cblume55f2d2d2016-02-26 13:20:48 -0800140 desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
Brian Salomond17b4a62017-05-23 16:53:47 -0400141 // Attempt to catch un- or wrongly initialized sample counts.
egdanielb0e1be22015-04-22 13:27:39 -0700142 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
143
144 desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
145
Brian Salomond17b4a62017-05-23 16:53:47 -0400146 if (texels.count() && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
147 return nullptr;
148 }
149
Robert Phillips92de6312017-05-23 07:43:48 -0400150 this->handleDirtyContext();
151 GrTexture* tex = this->onCreateTexture(desc, budgeted, texels);
bsalomonb12ea412015-02-02 21:19:50 -0800152 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800153 if (!caps->reuseScratchTextures() && !isRT) {
154 tex->resourcePriv().removeScratchKey();
155 }
bsalomonb12ea412015-02-02 21:19:50 -0800156 fStats.incTextureCreates();
cblume55f2d2d2016-02-26 13:20:48 -0800157 if (!texels.empty()) {
158 if (texels[0].fPixels) {
159 fStats.incTextureUploads();
160 }
bsalomonb12ea412015-02-02 21:19:50 -0800161 }
162 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000163 return tex;
164}
165
Greg Daniel7ef28f32017-04-20 16:41:55 +0000166sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
167 GrSurfaceOrigin origin,
168 GrBackendTextureFlags flags,
169 int sampleCnt,
bungeman6bd52842016-10-27 09:30:08 -0700170 GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000171 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000172 if (!this->caps()->isConfigTexturable(backendTex.config())) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800173 return nullptr;
174 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000175 if ((flags & kRenderTarget_GrBackendTextureFlag) &&
176 !this->caps()->isConfigRenderable(backendTex.config(), sampleCnt > 0)) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800177 return nullptr;
178 }
ericrkf7b8b8a2016-02-24 14:49:51 -0800179 int maxSize = this->caps()->maxTextureSize();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000180 if (backendTex.width() > maxSize || backendTex.height() > maxSize) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800181 return nullptr;
182 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000183 sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, origin, flags, sampleCnt,
184 ownership);
bungeman6bd52842016-10-27 09:30:08 -0700185 if (!tex) {
halcanary96fcdcc2015-08-27 07:41:13 -0700186 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000187 }
Eric Karl5c779752017-05-08 12:02:07 -0700188
189 if (!this->caps()->avoidStencilBuffers()) {
190 // TODO: defer this and attach dynamically
191 GrRenderTarget* tgt = tex->asRenderTarget();
192 if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
193 return nullptr;
194 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000195 }
bungeman6bd52842016-10-27 09:30:08 -0700196 return tex;
bsalomon@google.come269f212011-11-07 13:29:52 +0000197}
198
Greg Danielbcf612b2017-05-01 13:50:58 +0000199sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT,
200 GrSurfaceOrigin origin) {
201 if (!this->caps()->isConfigRenderable(backendRT.config(), backendRT.sampleCnt() > 0)) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800202 return nullptr;
203 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000204 this->handleDirtyContext();
Greg Danielbcf612b2017-05-01 13:50:58 +0000205 return this->onWrapBackendRenderTarget(backendRT, origin);
bsalomon@google.come269f212011-11-07 13:29:52 +0000206}
207
Greg Daniel7ef28f32017-04-20 16:41:55 +0000208sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
209 GrSurfaceOrigin origin,
210 int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800211 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000212 if (!this->caps()->isConfigRenderable(tex.config(), sampleCnt > 0)) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800213 return nullptr;
214 }
215 int maxSize = this->caps()->maxTextureSize();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000216 if (tex.width() > maxSize || tex.height() > maxSize) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800217 return nullptr;
218 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000219 return this->onWrapBackendTextureAsRenderTarget(tex, origin, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800220}
221
cdaltone2e71c22016-04-07 18:13:29 -0700222GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700223 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000224 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700225 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700226 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700227 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700228 }
cdalton397536c2016-03-25 12:15:03 -0700229 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800230}
231
Robert Phillipse3302df2017-04-24 07:31:02 -0400232std::unique_ptr<gr_instanced::OpAllocator> GrGpu::createInstancedRenderingAllocator() {
233 SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
234 return this->onCreateInstancedRenderingAllocator();
235}
236
csmartdaltone0d36292016-07-29 08:14:20 -0700237gr_instanced::InstancedRendering* GrGpu::createInstancedRendering() {
238 SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
239 return this->onCreateInstancedRendering();
240}
241
joshualitt1cbdcde2015-08-21 11:53:29 -0700242bool GrGpu::copySurface(GrSurface* dst,
243 GrSurface* src,
244 const SkIRect& srcRect,
245 const SkIPoint& dstPoint) {
246 SkASSERT(dst && src);
247 this->handleDirtyContext();
Brian Salomonbf7b6202016-11-11 16:08:03 -0500248 // We don't allow conversion between integer configs and float/fixed configs.
249 if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
250 return false;
251 }
joshualitt1cbdcde2015-08-21 11:53:29 -0700252 return this->onCopySurface(dst, src, srcRect, dstPoint);
253}
254
bsalomonf0674512015-07-28 13:26:15 -0700255bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
256 GrPixelConfig readConfig, DrawPreference* drawPreference,
257 ReadPixelTempDrawInfo* tempDrawInfo) {
258 SkASSERT(drawPreference);
259 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500260 SkASSERT(srcSurface);
bsalomonf0674512015-07-28 13:26:15 -0700261 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
262
egdaniel3fe03272016-08-15 10:59:17 -0700263 // We currently do not support reading into the packed formats 565 or 4444 as they are not
264 // required to have read back support on all devices and backends.
265 if (kRGB_565_GrPixelConfig == readConfig || kRGBA_4444_GrPixelConfig == readConfig) {
266 return false;
267 }
268
Brian Salomond17b4a62017-05-23 16:53:47 -0400269 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700270 tempDrawInfo)) {
271 return false;
272 }
273
274 // Check to see if we're going to request that the caller draw when drawing is not possible.
275 if (!srcSurface->asTexture() ||
276 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
277 // If we don't have a fallback to a straight read then fail.
278 if (kRequireDraw_DrawPreference == *drawPreference) {
279 return false;
280 }
281 *drawPreference = kNoDraw_DrawPreference;
282 }
283
284 return true;
285}
cblumeed828002016-02-16 13:00:01 -0800286bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700287 GrPixelConfig srcConfig, DrawPreference* drawPreference,
288 WritePixelTempDrawInfo* tempDrawInfo) {
289 SkASSERT(drawPreference);
290 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500291 SkASSERT(dstSurface);
bsalomonf0674512015-07-28 13:26:15 -0700292 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
293
bsalomonbabafcc2016-02-16 11:36:47 -0800294 if (SkToBool(dstSurface->asRenderTarget())) {
295 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
296 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
297 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
298 (width < dstSurface->width() || height < dstSurface->height())) {
299 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
300 }
bsalomonf0674512015-07-28 13:26:15 -0700301 }
302
cblumeed828002016-02-16 13:00:01 -0800303 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700304 tempDrawInfo)) {
305 return false;
306 }
307
308 // Check to see if we're going to request that the caller draw when drawing is not possible.
309 if (!dstSurface->asRenderTarget() ||
310 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
311 // If we don't have a fallback to a straight upload then fail.
312 if (kRequireDraw_DrawPreference == *drawPreference ||
313 !this->caps()->isConfigTexturable(srcConfig)) {
314 return false;
315 }
316 *drawPreference = kNoDraw_DrawPreference;
317 }
318 return true;
319}
320
bsalomon6cb3cbe2015-07-30 07:34:27 -0700321bool GrGpu::readPixels(GrSurface* surface,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000322 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000323 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000324 size_t rowBytes) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500325 SkASSERT(surface);
326
327 // We don't allow conversion between integer configs and float/fixed configs.
328 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
329 return false;
330 }
egdaniel6d901da2015-07-30 12:02:15 -0700331
egdaniel6d901da2015-07-30 12:02:15 -0700332 size_t bpp = GrBytesPerPixel(config);
333 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
334 &left, &top, &width, &height,
335 &buffer,
336 &rowBytes)) {
337 return false;
338 }
339
Brian Salomonbf7b6202016-11-11 16:08:03 -0500340 this->handleDirtyContext();
341
egdaniel6d901da2015-07-30 12:02:15 -0700342 return this->onReadPixels(surface,
343 left, top, width, height,
344 config, buffer,
345 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000346}
347
bsalomon6cb3cbe2015-07-30 07:34:27 -0700348bool GrGpu::writePixels(GrSurface* surface,
349 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800350 GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500351 SkASSERT(surface);
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400352
cblume55f2d2d2016-02-26 13:20:48 -0800353 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800354 if (!texels[currentMipLevel].fPixels ) {
355 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800356 }
357 }
jvanverth2dc29942015-09-01 07:16:46 -0700358
Brian Salomonbf7b6202016-11-11 16:08:03 -0500359 // We don't allow conversion between integer configs and float/fixed configs.
360 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
361 return false;
362 }
363
bsalomon@google.com6f379512011-11-16 20:36:03 +0000364 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800365 if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700366 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
367 this->didWriteToSurface(surface, &rect, texels.count());
bsalomonb12ea412015-02-02 21:19:50 -0800368 fStats.incTextureUploads();
369 return true;
370 }
371 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000372}
373
cblume55f2d2d2016-02-26 13:20:48 -0800374bool GrGpu::writePixels(GrSurface* surface,
375 int left, int top, int width, int height,
376 GrPixelConfig config, const void* buffer,
377 size_t rowBytes) {
378 GrMipLevel mipLevel;
379 mipLevel.fPixels = buffer;
380 mipLevel.fRowBytes = rowBytes;
381 SkSTArray<1, GrMipLevel> texels;
382 texels.push_back(mipLevel);
383
384 return this->writePixels(surface, left, top, width, height, config, texels);
385}
386
jvanverthc3d706f2016-04-20 10:33:27 -0700387bool GrGpu::transferPixels(GrSurface* surface,
jvanverth17aa0472016-01-05 10:41:27 -0800388 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700389 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth84741b32016-09-30 08:39:02 -0700390 size_t offset, size_t rowBytes, GrFence* fence) {
cdalton397536c2016-03-25 12:15:03 -0700391 SkASSERT(transferBuffer);
jvanverth84741b32016-09-30 08:39:02 -0700392 SkASSERT(fence);
jvanverth17aa0472016-01-05 10:41:27 -0800393
Brian Salomonbf7b6202016-11-11 16:08:03 -0500394 // We don't allow conversion between integer configs and float/fixed configs.
395 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
396 return false;
397 }
398
jvanverth17aa0472016-01-05 10:41:27 -0800399 this->handleDirtyContext();
jvanverthc3d706f2016-04-20 10:33:27 -0700400 if (this->onTransferPixels(surface, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700401 transferBuffer, offset, rowBytes)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700402 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
403 this->didWriteToSurface(surface, &rect);
jvanverth17aa0472016-01-05 10:41:27 -0800404 fStats.incTransfersToTexture();
jvanverth84741b32016-09-30 08:39:02 -0700405
406 if (*fence) {
407 this->deleteFence(*fence);
408 }
409 *fence = this->insertFence();
410
jvanverth17aa0472016-01-05 10:41:27 -0800411 return true;
412 }
413 return false;
414}
415
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000416void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000417 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000418 this->handleDirtyContext();
419 this->onResolveRenderTarget(target);
420}
421
jvanverth900bd4a2016-04-29 13:53:12 -0700422void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
423 SkASSERT(surface);
424 // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
425 if (nullptr == bounds || !bounds->isEmpty()) {
426 if (GrRenderTarget* target = surface->asRenderTarget()) {
427 target->flagAsNeedingResolve(bounds);
428 }
429 GrTexture* texture = surface->asTexture();
430 if (texture && 1 == mipLevels) {
431 texture->texturePriv().dirtyMipMaps(true);
432 }
433 }
434}
435
csmartdaltonc633abb2016-11-01 08:55:55 -0700436const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
437 GrRenderTarget* rt = pipeline.getRenderTarget();
Brian Salomon154ce912017-05-17 10:40:02 -0400438 SkASSERT(rt->numStencilSamples() > 1);
csmartdalton0d28e572016-07-06 09:59:43 -0700439
csmartdaltonc633abb2016-11-01 08:55:55 -0700440 GrStencilSettings stencil;
441 if (pipeline.isStencilEnabled()) {
442 // TODO: attach stencil and create settings during render target flush.
443 SkASSERT(rt->renderTargetPriv().getStencilAttachment());
444 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
445 rt->renderTargetPriv().numStencilBits());
446 }
447
cdalton28f45b92016-03-07 13:58:26 -0800448 int effectiveSampleCnt;
csmartdalton0d28e572016-07-06 09:59:43 -0700449 SkSTArray<16, SkPoint, true> pattern;
csmartdaltonc25c5d72016-11-01 07:03:59 -0700450 this->onQueryMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern);
Brian Salomon154ce912017-05-17 10:40:02 -0400451 SkASSERT(effectiveSampleCnt >= rt->numStencilSamples());
csmartdalton0d28e572016-07-06 09:59:43 -0700452
453 uint8_t id;
454 if (this->caps()->sampleLocationsSupport()) {
455 SkASSERT(pattern.count() == effectiveSampleCnt);
456 const auto& insertResult = fMultisampleSpecsIdMap.insert(
457 MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
458 id = insertResult.first->second;
459 if (insertResult.second) {
460 // This means the insert did not find the pattern in the map already, and therefore an
461 // actual insertion took place. (We don't expect to see many unique sample patterns.)
462 const SkPoint* sampleLocations = insertResult.first->first.begin();
463 SkASSERT(id == fMultisampleSpecs.count());
464 fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
465 }
466 } else {
467 id = effectiveSampleCnt;
468 for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
469 fMultisampleSpecs.emplace_back(i, i, nullptr);
470 }
cdalton28f45b92016-03-07 13:58:26 -0800471 }
csmartdalton0d28e572016-07-06 09:59:43 -0700472 SkASSERT(id > 0);
csmartdalton0d28e572016-07-06 09:59:43 -0700473
csmartdalton0d28e572016-07-06 09:59:43 -0700474 return fMultisampleSpecs[id];
cdalton28f45b92016-03-07 13:58:26 -0800475}
476
csmartdalton0d28e572016-07-06 09:59:43 -0700477bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
478 const SamplePattern& b) const {
479 if (a.count() != b.count()) {
480 return a.count() < b.count();
481 }
482 for (int i = 0; i < a.count(); ++i) {
483 // This doesn't have geometric meaning. We just need to define an ordering for std::map.
484 if (a[i].x() != b[i].x()) {
485 return a[i].x() < b[i].x();
486 }
487 if (a[i].y() != b[i].y()) {
488 return a[i].y() < b[i].y();
489 }
490 }
491 return false; // Equal.
492}