blob: 5b338cdfa0f7c7fd5a7e75d232d0e3f96b4d6491 [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 Daniel51316782017-08-02 15:10:09 +000011#include "GrBackendSemaphore.h"
Greg Daniel7ef28f32017-04-20 16:41:55 +000012#include "GrBackendSurface.h"
cdalton397536c2016-03-25 12:15:03 -070013#include "GrBuffer.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070014#include "GrCaps.h"
bsalomon@google.com558a75b2011-08-08 17:01:14 +000015#include "GrContext.h"
bsalomon3582d3e2015-02-13 14:20:05 -080016#include "GrGpuResourcePriv.h"
egdaniel0e1853c2016-03-17 11:35:45 -070017#include "GrMesh.h"
kkinnunencabe20c2015-06-01 01:37:26 -070018#include "GrPathRendering.h"
bsalomoncb02b382015-08-12 11:14:50 -070019#include "GrPipeline.h"
Robert Phillipsfbcef6e2017-06-15 12:07:18 -040020#include "GrRenderTargetPriv.h"
bsalomon0ea80f42015-02-11 10:49:59 -080021#include "GrResourceCache.h"
egdanielec00d942015-09-14 12:56:10 -070022#include "GrResourceProvider.h"
Greg Daniel51316782017-08-02 15:10:09 +000023#include "GrSemaphore.h"
egdaniel8dc7c3a2015-04-16 11:22:42 -070024#include "GrStencilAttachment.h"
csmartdaltonc633abb2016-11-01 08:55:55 -070025#include "GrStencilSettings.h"
egdaniel6d901da2015-07-30 12:02:15 -070026#include "GrSurfacePriv.h"
jvanverth900bd4a2016-04-29 13:53:12 -070027#include "GrTexturePriv.h"
Brian Salomondcbb9d92017-07-19 10:53:20 -040028#include "GrTracing.h"
Brian Osman71a18892017-08-10 10:23:25 -040029#include "SkJSONWriter.h"
halcanary4dbbd042016-06-07 17:21:10 -070030#include "SkMathPriv.h"
bsalomoncb8979d2015-05-05 09:51:38 -070031
bsalomon@google.comd302f142011-03-03 13:54:13 +000032////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000033
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000034GrGpu::GrGpu(GrContext* context)
joshualitt3322fa42014-11-07 08:48:51 -080035 : fResetTimestamp(kExpiredTimestamp+1)
bsalomon@google.com0a208a12013-06-28 18:57:35 +000036 , fResetBits(kAll_GrBackendState)
joshualitt3322fa42014-11-07 08:48:51 -080037 , fContext(context) {
csmartdalton0d28e572016-07-06 09:59:43 -070038 fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
reed@google.comac10a2d2010-12-22 21:39:39 +000039}
40
bsalomoned0bcad2015-05-04 10:36:42 -070041GrGpu::~GrGpu() {}
bsalomon1d89ddc2014-08-19 14:20:58 -070042
bsalomon6e2aad42016-04-01 11:54:31 -070043void GrGpu::disconnect(DisconnectType) {}
reed@google.comac10a2d2010-12-22 21:39:39 +000044
bsalomon@google.comd302f142011-03-03 13:54:13 +000045////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000046
Robert Phillips81444fb2017-03-21 09:14:35 -040047bool GrGpu::isACopyNeededForTextureParams(int width, int height,
Brian Salomon2bbdcc42017-09-07 12:36:34 -040048 const GrSamplerState& textureParams,
Robert Phillips81444fb2017-03-21 09:14:35 -040049 GrTextureProducer::CopyParams* copyParams,
50 SkScalar scaleAdjust[2]) const {
bsalomon045802d2015-10-20 07:58:01 -070051 const GrCaps& caps = *this->caps();
Brian Salomon2bbdcc42017-09-07 12:36:34 -040052 if (textureParams.isRepeated() && !caps.npotTextureTileSupport() &&
bsalomon045802d2015-10-20 07:58:01 -070053 (!SkIsPow2(width) || !SkIsPow2(height))) {
Robert Phillips67c18d62017-01-20 12:44:06 -050054 SkASSERT(scaleAdjust);
bsalomon100b8f82015-10-28 08:37:44 -070055 copyParams->fWidth = GrNextPow2(width);
56 copyParams->fHeight = GrNextPow2(height);
Robert Phillips67c18d62017-01-20 12:44:06 -050057 scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
58 scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040059 switch (textureParams.filter()) {
60 case GrSamplerState::Filter::kNearest:
61 copyParams->fFilter = GrSamplerState::Filter::kNearest;
bsalomon045802d2015-10-20 07:58:01 -070062 break;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040063 case GrSamplerState::Filter::kBilerp:
64 case GrSamplerState::Filter::kMipMap:
bsalomon045802d2015-10-20 07:58:01 -070065 // We are only ever scaling up so no reason to ever indicate kMipMap.
Brian Salomon2bbdcc42017-09-07 12:36:34 -040066 copyParams->fFilter = GrSamplerState::Filter::kBilerp;
bsalomon045802d2015-10-20 07:58:01 -070067 break;
68 }
bsalomon100b8f82015-10-28 08:37:44 -070069 return true;
bsalomon045802d2015-10-20 07:58:01 -070070 }
bsalomon100b8f82015-10-28 08:37:44 -070071 return false;
bsalomon045802d2015-10-20 07:58:01 -070072}
73
cblume55f2d2d2016-02-26 13:20:48 -080074/**
75 * Prior to creating a texture, make sure the type of texture being created is
76 * supported by calling check_texture_creation_params.
77 *
Robert Phillips590533f2017-07-11 14:22:35 -040078 * @param caps The capabilities of the GL device.
79 * @param desc The descriptor of the texture to create.
80 * @param isRT Indicates if the texture can be a render target.
81 * @param texels The texel data for the mipmap levels
82 * @param mipLevelCount The number of GrMipLevels in 'texels'
cblume55f2d2d2016-02-26 13:20:48 -080083 */
84static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
Robert Phillips590533f2017-07-11 14:22:35 -040085 bool* isRT,
86 const GrMipLevel texels[], int mipLevelCount) {
cblume55f2d2d2016-02-26 13:20:48 -080087 if (!caps.isConfigTexturable(desc.fConfig)) {
88 return false;
robertphillips@google.comd3eb3362012-10-31 13:56:35 +000089 }
krajcevski9c0e6292014-06-02 07:38:14 -070090
Robert Phillips590533f2017-07-11 14:22:35 -040091 if (GrPixelConfigIsSint(desc.fConfig) && mipLevelCount > 1) {
Brian Salomonbf7b6202016-11-11 16:08:03 -050092 return false;
93 }
94
cblume55f2d2d2016-02-26 13:20:48 -080095 *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
96 if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
97 return false;
commit-bot@chromium.org6b7938f2013-10-15 14:18:16 +000098 }
robertphillips@google.comd3eb3362012-10-31 13:56:35 +000099
robertphillips6e83ac72015-08-13 05:19:14 -0700100 // We currently do not support multisampled textures
cblume55f2d2d2016-02-26 13:20:48 -0800101 if (!*isRT && desc.fSampleCnt > 0) {
102 return false;
103 }
104
105 if (*isRT) {
106 int maxRTSize = caps.maxRenderTargetSize();
107 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
108 return false;
109 }
110 } else {
111 int maxSize = caps.maxTextureSize();
112 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
113 return false;
114 }
115 }
bsalomone699d0c2016-03-09 06:25:15 -0800116
cblume55f2d2d2016-02-26 13:20:48 -0800117 return true;
118}
119
Robert Phillips67d52cf2017-06-05 13:38:13 -0400120sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
Robert Phillips590533f2017-07-11 14:22:35 -0400121 const GrMipLevel texels[], int mipLevelCount) {
Brian Salomondcbb9d92017-07-19 10:53:20 -0400122 GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "createTexture", fContext);
cblume55f2d2d2016-02-26 13:20:48 -0800123 GrSurfaceDesc desc = origDesc;
124
125 const GrCaps* caps = this->caps();
126 bool isRT = false;
Robert Phillips590533f2017-07-11 14:22:35 -0400127 bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT,
128 texels, mipLevelCount);
cblume55f2d2d2016-02-26 13:20:48 -0800129 if (!textureCreationParamsValid) {
halcanary96fcdcc2015-08-27 07:41:13 -0700130 return nullptr;
egdaniel8c9b6f12015-05-12 13:36:30 -0700131 }
132
Greg Daniel81e7bf82017-07-19 14:47:42 -0400133 desc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
Brian Salomond17b4a62017-05-23 16:53:47 -0400134 // Attempt to catch un- or wrongly initialized sample counts.
egdanielb0e1be22015-04-22 13:27:39 -0700135 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
egdanielb0e1be22015-04-22 13:27:39 -0700136
Robert Phillips590533f2017-07-11 14:22:35 -0400137 if (mipLevelCount && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
Brian Salomond17b4a62017-05-23 16:53:47 -0400138 return nullptr;
139 }
140
Robert Phillips92de6312017-05-23 07:43:48 -0400141 this->handleDirtyContext();
Robert Phillips590533f2017-07-11 14:22:35 -0400142 sk_sp<GrTexture> tex = this->onCreateTexture(desc, budgeted, texels, mipLevelCount);
bsalomonb12ea412015-02-02 21:19:50 -0800143 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800144 if (!caps->reuseScratchTextures() && !isRT) {
145 tex->resourcePriv().removeScratchKey();
146 }
bsalomonb12ea412015-02-02 21:19:50 -0800147 fStats.incTextureCreates();
Robert Phillips590533f2017-07-11 14:22:35 -0400148 if (mipLevelCount) {
cblume55f2d2d2016-02-26 13:20:48 -0800149 if (texels[0].fPixels) {
150 fStats.incTextureUploads();
151 }
bsalomonb12ea412015-02-02 21:19:50 -0800152 }
153 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000154 return tex;
155}
156
Robert Phillips646e4292017-06-13 12:44:56 -0400157sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted) {
Robert Phillips590533f2017-07-11 14:22:35 -0400158 return this->createTexture(desc, budgeted, nullptr, 0);
Robert Phillips646e4292017-06-13 12:44:56 -0400159}
160
Greg Daniel7ef28f32017-04-20 16:41:55 +0000161sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
bungeman6bd52842016-10-27 09:30:08 -0700162 GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000163 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000164 if (!this->caps()->isConfigTexturable(backendTex.config())) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800165 return nullptr;
166 }
Brian Salomond17f6582017-07-19 18:28:58 -0400167 if (backendTex.width() > this->caps()->maxTextureSize() ||
168 backendTex.height() > this->caps()->maxTextureSize()) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800169 return nullptr;
170 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400171 sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, ownership);
bungeman6bd52842016-10-27 09:30:08 -0700172 if (!tex) {
halcanary96fcdcc2015-08-27 07:41:13 -0700173 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000174 }
Brian Salomond17f6582017-07-19 18:28:58 -0400175 return tex;
176}
Eric Karl5c779752017-05-08 12:02:07 -0700177
Brian Salomond17f6582017-07-19 18:28:58 -0400178sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400179 int sampleCnt, GrWrapOwnership ownership) {
Brian Salomond17f6582017-07-19 18:28:58 -0400180 this->handleDirtyContext();
181 if (!this->caps()->isConfigTexturable(backendTex.config()) ||
182 !this->caps()->isConfigRenderable(backendTex.config(), sampleCnt > 0)) {
183 return nullptr;
184 }
185
186 if (backendTex.width() > this->caps()->maxRenderTargetSize() ||
187 backendTex.height() > this->caps()->maxRenderTargetSize()) {
188 return nullptr;
189 }
Robert Phillipsc0192e32017-09-21 12:00:26 -0400190 sk_sp<GrTexture> tex = this->onWrapRenderableBackendTexture(backendTex, sampleCnt, ownership);
Brian Salomond17f6582017-07-19 18:28:58 -0400191 if (!tex) {
192 return nullptr;
193 }
194 SkASSERT(tex->asRenderTarget());
bungeman6bd52842016-10-27 09:30:08 -0700195 return tex;
bsalomon@google.come269f212011-11-07 13:29:52 +0000196}
197
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400198sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
Greg Danielbcf612b2017-05-01 13:50:58 +0000199 if (!this->caps()->isConfigRenderable(backendRT.config(), backendRT.sampleCnt() > 0)) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800200 return nullptr;
201 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000202 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400203 return this->onWrapBackendRenderTarget(backendRT);
bsalomon@google.come269f212011-11-07 13:29:52 +0000204}
205
Greg Daniel7ef28f32017-04-20 16:41:55 +0000206sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000207 int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800208 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000209 if (!this->caps()->isConfigRenderable(tex.config(), sampleCnt > 0)) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800210 return nullptr;
211 }
212 int maxSize = this->caps()->maxTextureSize();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000213 if (tex.width() > maxSize || tex.height() > maxSize) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800214 return nullptr;
215 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400216 return this->onWrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800217}
218
cdaltone2e71c22016-04-07 18:13:29 -0700219GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700220 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000221 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700222 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700223 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700224 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700225 }
cdalton397536c2016-03-25 12:15:03 -0700226 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800227}
228
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400229bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
230 GrSurface* src, GrSurfaceOrigin srcOrigin,
231 const SkIRect& srcRect, const SkIPoint& dstPoint) {
Brian Salomondcbb9d92017-07-19 10:53:20 -0400232 GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
joshualitt1cbdcde2015-08-21 11:53:29 -0700233 SkASSERT(dst && src);
234 this->handleDirtyContext();
Brian Salomonbf7b6202016-11-11 16:08:03 -0500235 // We don't allow conversion between integer configs and float/fixed configs.
236 if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
237 return false;
238 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400239 return this->onCopySurface(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
joshualitt1cbdcde2015-08-21 11:53:29 -0700240}
241
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400242bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
243 int width, int height, size_t rowBytes,
bsalomonf0674512015-07-28 13:26:15 -0700244 GrPixelConfig readConfig, DrawPreference* drawPreference,
245 ReadPixelTempDrawInfo* tempDrawInfo) {
246 SkASSERT(drawPreference);
247 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500248 SkASSERT(srcSurface);
bsalomonf0674512015-07-28 13:26:15 -0700249 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
250
egdaniel3fe03272016-08-15 10:59:17 -0700251 // We currently do not support reading into the packed formats 565 or 4444 as they are not
252 // required to have read back support on all devices and backends.
253 if (kRGB_565_GrPixelConfig == readConfig || kRGBA_4444_GrPixelConfig == readConfig) {
254 return false;
255 }
256
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400257 if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, readConfig,
258 drawPreference, tempDrawInfo)) {
bsalomonf0674512015-07-28 13:26:15 -0700259 return false;
260 }
261
262 // Check to see if we're going to request that the caller draw when drawing is not possible.
263 if (!srcSurface->asTexture() ||
264 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
265 // If we don't have a fallback to a straight read then fail.
266 if (kRequireDraw_DrawPreference == *drawPreference) {
267 return false;
268 }
269 *drawPreference = kNoDraw_DrawPreference;
270 }
271
272 return true;
273}
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400274bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
275 int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700276 GrPixelConfig srcConfig, DrawPreference* drawPreference,
277 WritePixelTempDrawInfo* tempDrawInfo) {
278 SkASSERT(drawPreference);
279 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500280 SkASSERT(dstSurface);
bsalomonf0674512015-07-28 13:26:15 -0700281 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
282
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400283 if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700284 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 (!dstSurface->asRenderTarget() ||
290 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
291 // If we don't have a fallback to a straight upload then fail.
292 if (kRequireDraw_DrawPreference == *drawPreference ||
293 !this->caps()->isConfigTexturable(srcConfig)) {
294 return false;
295 }
296 *drawPreference = kNoDraw_DrawPreference;
297 }
298 return true;
299}
300
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400301bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000302 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000303 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000304 size_t rowBytes) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500305 SkASSERT(surface);
306
307 // We don't allow conversion between integer configs and float/fixed configs.
308 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
309 return false;
310 }
egdaniel6d901da2015-07-30 12:02:15 -0700311
egdaniel6d901da2015-07-30 12:02:15 -0700312 size_t bpp = GrBytesPerPixel(config);
313 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
314 &left, &top, &width, &height,
315 &buffer,
316 &rowBytes)) {
317 return false;
318 }
319
Brian Salomonbf7b6202016-11-11 16:08:03 -0500320 this->handleDirtyContext();
321
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400322 return this->onReadPixels(surface, origin,
egdaniel6d901da2015-07-30 12:02:15 -0700323 left, top, width, height,
324 config, buffer,
325 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000326}
327
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400328bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700329 int left, int top, int width, int height,
Robert Phillips590533f2017-07-11 14:22:35 -0400330 GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500331 SkASSERT(surface);
Robert Phillips590533f2017-07-11 14:22:35 -0400332 if (1 == mipLevelCount) {
Greg Daniel660cc992017-06-26 14:55:05 -0400333 // We require that if we are not mipped, then the write region is contained in the surface
334 SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
335 SkIRect bounds = SkIRect::MakeWH(surface->width(), surface->height());
336 if (!bounds.contains(subRect)) {
337 return false;
338 }
339 } else if (0 != left || 0 != top || width != surface->width() || height != surface->height()) {
340 // We require that if the texels are mipped, than the write region is the entire surface
341 return false;
342 }
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400343
Robert Phillips590533f2017-07-11 14:22:35 -0400344 for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800345 if (!texels[currentMipLevel].fPixels ) {
346 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800347 }
348 }
jvanverth2dc29942015-09-01 07:16:46 -0700349
Brian Salomonbf7b6202016-11-11 16:08:03 -0500350 // We don't allow conversion between integer configs and float/fixed configs.
351 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
352 return false;
353 }
354
bsalomon@google.com6f379512011-11-16 20:36:03 +0000355 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400356 if (this->onWritePixels(surface, origin, left, top, width, height, config,
357 texels, mipLevelCount)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700358 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
Robert Phillips590533f2017-07-11 14:22:35 -0400359 this->didWriteToSurface(surface, &rect, mipLevelCount);
bsalomonb12ea412015-02-02 21:19:50 -0800360 fStats.incTextureUploads();
361 return true;
362 }
363 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000364}
365
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400366bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
cblume55f2d2d2016-02-26 13:20:48 -0800367 int left, int top, int width, int height,
368 GrPixelConfig config, const void* buffer,
369 size_t rowBytes) {
Robert Phillips590533f2017-07-11 14:22:35 -0400370 GrMipLevel mipLevel = { buffer, rowBytes };
cblume55f2d2d2016-02-26 13:20:48 -0800371
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400372 return this->writePixels(surface, origin, left, top, width, height, config, &mipLevel, 1);
cblume55f2d2d2016-02-26 13:20:48 -0800373}
374
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400375bool GrGpu::transferPixels(GrTexture* texture,
jvanverth17aa0472016-01-05 10:41:27 -0800376 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700377 GrPixelConfig config, GrBuffer* transferBuffer,
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400378 size_t offset, size_t rowBytes) {
cdalton397536c2016-03-25 12:15:03 -0700379 SkASSERT(transferBuffer);
jvanverth17aa0472016-01-05 10:41:27 -0800380
Brian Salomonbf7b6202016-11-11 16:08:03 -0500381 // We don't allow conversion between integer configs and float/fixed configs.
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400382 if (GrPixelConfigIsSint(texture->config()) != GrPixelConfigIsSint(config)) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500383 return false;
384 }
385
Greg Daniel660cc992017-06-26 14:55:05 -0400386 // We require that the write region is contained in the texture
387 SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
388 SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
389 if (!bounds.contains(subRect)) {
390 return false;
391 }
392
jvanverth17aa0472016-01-05 10:41:27 -0800393 this->handleDirtyContext();
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400394 if (this->onTransferPixels(texture, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700395 transferBuffer, offset, rowBytes)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700396 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400397 this->didWriteToSurface(texture, &rect);
jvanverth17aa0472016-01-05 10:41:27 -0800398 fStats.incTransfersToTexture();
jvanverth84741b32016-09-30 08:39:02 -0700399
jvanverth17aa0472016-01-05 10:41:27 -0800400 return true;
401 }
402 return false;
403}
404
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400405void GrGpu::resolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000406 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000407 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400408 this->onResolveRenderTarget(target, origin);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000409}
410
jvanverth900bd4a2016-04-29 13:53:12 -0700411void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
412 SkASSERT(surface);
413 // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
414 if (nullptr == bounds || !bounds->isEmpty()) {
415 if (GrRenderTarget* target = surface->asRenderTarget()) {
416 target->flagAsNeedingResolve(bounds);
417 }
418 GrTexture* texture = surface->asTexture();
419 if (texture && 1 == mipLevels) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -0400420 texture->texturePriv().markMipMapsDirty();
jvanverth900bd4a2016-04-29 13:53:12 -0700421 }
422 }
423}
424
csmartdaltonc633abb2016-11-01 08:55:55 -0700425const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400426 GrRenderTarget* rt = pipeline.renderTarget();
Brian Salomon154ce912017-05-17 10:40:02 -0400427 SkASSERT(rt->numStencilSamples() > 1);
csmartdalton0d28e572016-07-06 09:59:43 -0700428
csmartdaltonc633abb2016-11-01 08:55:55 -0700429 GrStencilSettings stencil;
430 if (pipeline.isStencilEnabled()) {
431 // TODO: attach stencil and create settings during render target flush.
432 SkASSERT(rt->renderTargetPriv().getStencilAttachment());
433 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
434 rt->renderTargetPriv().numStencilBits());
435 }
436
cdalton28f45b92016-03-07 13:58:26 -0800437 int effectiveSampleCnt;
csmartdalton0d28e572016-07-06 09:59:43 -0700438 SkSTArray<16, SkPoint, true> pattern;
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400439 this->onQueryMultisampleSpecs(rt, pipeline.proxy()->origin(), stencil,
440 &effectiveSampleCnt, &pattern);
Brian Salomon154ce912017-05-17 10:40:02 -0400441 SkASSERT(effectiveSampleCnt >= rt->numStencilSamples());
csmartdalton0d28e572016-07-06 09:59:43 -0700442
443 uint8_t id;
444 if (this->caps()->sampleLocationsSupport()) {
445 SkASSERT(pattern.count() == effectiveSampleCnt);
446 const auto& insertResult = fMultisampleSpecsIdMap.insert(
447 MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
448 id = insertResult.first->second;
449 if (insertResult.second) {
450 // This means the insert did not find the pattern in the map already, and therefore an
451 // actual insertion took place. (We don't expect to see many unique sample patterns.)
452 const SkPoint* sampleLocations = insertResult.first->first.begin();
453 SkASSERT(id == fMultisampleSpecs.count());
454 fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
455 }
456 } else {
457 id = effectiveSampleCnt;
458 for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
459 fMultisampleSpecs.emplace_back(i, i, nullptr);
460 }
cdalton28f45b92016-03-07 13:58:26 -0800461 }
csmartdalton0d28e572016-07-06 09:59:43 -0700462 SkASSERT(id > 0);
csmartdalton0d28e572016-07-06 09:59:43 -0700463
csmartdalton0d28e572016-07-06 09:59:43 -0700464 return fMultisampleSpecs[id];
cdalton28f45b92016-03-07 13:58:26 -0800465}
466
csmartdalton0d28e572016-07-06 09:59:43 -0700467bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
468 const SamplePattern& b) const {
469 if (a.count() != b.count()) {
470 return a.count() < b.count();
471 }
472 for (int i = 0; i < a.count(); ++i) {
473 // This doesn't have geometric meaning. We just need to define an ordering for std::map.
474 if (a[i].x() != b[i].x()) {
475 return a[i].x() < b[i].x();
476 }
477 if (a[i].y() != b[i].y()) {
478 return a[i].y() < b[i].y();
479 }
480 }
481 return false; // Equal.
482}
Greg Daniel51316782017-08-02 15:10:09 +0000483
484GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
485 GrBackendSemaphore backendSemaphores[]) {
486 if (this->caps()->fenceSyncSupport()) {
487 for (int i = 0; i < numSemaphores; ++i) {
488 sk_sp<GrSemaphore> semaphore;
489 if (backendSemaphores[i].isInitialized()) {
490 semaphore = fContext->resourceProvider()->wrapBackendSemaphore(
491 backendSemaphores[i], kBorrow_GrWrapOwnership);
492 } else {
493 semaphore = fContext->resourceProvider()->makeSemaphore(false);
494 }
495 this->insertSemaphore(semaphore, false);
496
497 if (!backendSemaphores[i].isInitialized()) {
498 semaphore->setBackendSemaphore(&backendSemaphores[i]);
499 }
500 }
501 }
502 this->onFinishFlush((numSemaphores > 0 && this->caps()->fenceSyncSupport()));
503 return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes
504 : GrSemaphoresSubmitted::kNo;
505}
Brian Osman71a18892017-08-10 10:23:25 -0400506
507void GrGpu::dumpJSON(SkJSONWriter* writer) const {
508 writer->beginObject();
509
510 // TODO: Is there anything useful in the base class to dump here?
511
512 this->onDumpJSON(writer);
513
514 writer->endObject();
515}