blob: f42e5383b49e18e50bec145b217937332b2b2f12 [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,
48 const GrSamplerParams& textureParams,
49 GrTextureProducer::CopyParams* copyParams,
50 SkScalar scaleAdjust[2]) const {
bsalomon045802d2015-10-20 07:58:01 -070051 const GrCaps& caps = *this->caps();
52 if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
53 (!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;
bsalomon045802d2015-10-20 07:58:01 -070059 switch (textureParams.filterMode()) {
Brian Salomon514baff2016-11-17 15:17:07 -050060 case GrSamplerParams::kNone_FilterMode:
61 copyParams->fFilter = GrSamplerParams::kNone_FilterMode;
bsalomon045802d2015-10-20 07:58:01 -070062 break;
Brian Salomon514baff2016-11-17 15:17:07 -050063 case GrSamplerParams::kBilerp_FilterMode:
64 case GrSamplerParams::kMipMap_FilterMode:
bsalomon045802d2015-10-20 07:58:01 -070065 // We are only ever scaling up so no reason to ever indicate kMipMap.
Brian Salomon514baff2016-11-17 15:17:07 -050066 copyParams->fFilter = GrSamplerParams::kBilerp_FilterMode;
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
Robert Phillips590533f2017-07-11 14:22:35 -0400117 for (int i = 0; i < mipLevelCount; ++i) {
bsalomone699d0c2016-03-09 06:25:15 -0800118 if (!texels[i].fPixels) {
119 return false;
120 }
121 }
cblume55f2d2d2016-02-26 13:20:48 -0800122 return true;
123}
124
Robert Phillips67d52cf2017-06-05 13:38:13 -0400125sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
Robert Phillips590533f2017-07-11 14:22:35 -0400126 const GrMipLevel texels[], int mipLevelCount) {
Brian Salomondcbb9d92017-07-19 10:53:20 -0400127 GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "createTexture", fContext);
cblume55f2d2d2016-02-26 13:20:48 -0800128 GrSurfaceDesc desc = origDesc;
129
130 const GrCaps* caps = this->caps();
131 bool isRT = false;
Robert Phillips590533f2017-07-11 14:22:35 -0400132 bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT,
133 texels, mipLevelCount);
cblume55f2d2d2016-02-26 13:20:48 -0800134 if (!textureCreationParamsValid) {
halcanary96fcdcc2015-08-27 07:41:13 -0700135 return nullptr;
egdaniel8c9b6f12015-05-12 13:36:30 -0700136 }
137
Greg Daniel81e7bf82017-07-19 14:47:42 -0400138 desc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
Brian Salomond17b4a62017-05-23 16:53:47 -0400139 // Attempt to catch un- or wrongly initialized sample counts.
egdanielb0e1be22015-04-22 13:27:39 -0700140 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
egdanielb0e1be22015-04-22 13:27:39 -0700141
Robert Phillips590533f2017-07-11 14:22:35 -0400142 if (mipLevelCount && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
Brian Salomond17b4a62017-05-23 16:53:47 -0400143 return nullptr;
144 }
145
Robert Phillips92de6312017-05-23 07:43:48 -0400146 this->handleDirtyContext();
Robert Phillips590533f2017-07-11 14:22:35 -0400147 sk_sp<GrTexture> tex = this->onCreateTexture(desc, budgeted, texels, mipLevelCount);
bsalomonb12ea412015-02-02 21:19:50 -0800148 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800149 if (!caps->reuseScratchTextures() && !isRT) {
150 tex->resourcePriv().removeScratchKey();
151 }
bsalomonb12ea412015-02-02 21:19:50 -0800152 fStats.incTextureCreates();
Robert Phillips590533f2017-07-11 14:22:35 -0400153 if (mipLevelCount) {
cblume55f2d2d2016-02-26 13:20:48 -0800154 if (texels[0].fPixels) {
155 fStats.incTextureUploads();
156 }
bsalomonb12ea412015-02-02 21:19:50 -0800157 }
158 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000159 return tex;
160}
161
Robert Phillips646e4292017-06-13 12:44:56 -0400162sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted) {
Robert Phillips590533f2017-07-11 14:22:35 -0400163 return this->createTexture(desc, budgeted, nullptr, 0);
Robert Phillips646e4292017-06-13 12:44:56 -0400164}
165
Greg Daniel7ef28f32017-04-20 16:41:55 +0000166sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
bungeman6bd52842016-10-27 09:30:08 -0700167 GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000168 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000169 if (!this->caps()->isConfigTexturable(backendTex.config())) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800170 return nullptr;
171 }
Brian Salomond17f6582017-07-19 18:28:58 -0400172 if (backendTex.width() > this->caps()->maxTextureSize() ||
173 backendTex.height() > this->caps()->maxTextureSize()) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800174 return nullptr;
175 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400176 sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, ownership);
bungeman6bd52842016-10-27 09:30:08 -0700177 if (!tex) {
halcanary96fcdcc2015-08-27 07:41:13 -0700178 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000179 }
Brian Salomond17f6582017-07-19 18:28:58 -0400180 return tex;
181}
Eric Karl5c779752017-05-08 12:02:07 -0700182
Brian Salomond17f6582017-07-19 18:28:58 -0400183sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400184 int sampleCnt, GrWrapOwnership ownership) {
Brian Salomond17f6582017-07-19 18:28:58 -0400185 this->handleDirtyContext();
186 if (!this->caps()->isConfigTexturable(backendTex.config()) ||
187 !this->caps()->isConfigRenderable(backendTex.config(), sampleCnt > 0)) {
188 return nullptr;
189 }
190
191 if (backendTex.width() > this->caps()->maxRenderTargetSize() ||
192 backendTex.height() > this->caps()->maxRenderTargetSize()) {
193 return nullptr;
194 }
195 sk_sp<GrTexture> tex =
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400196 this->onWrapRenderableBackendTexture(backendTex, sampleCnt, ownership);
Brian Salomond17f6582017-07-19 18:28:58 -0400197 if (!tex) {
198 return nullptr;
199 }
200 SkASSERT(tex->asRenderTarget());
Eric Karl5c779752017-05-08 12:02:07 -0700201 if (!this->caps()->avoidStencilBuffers()) {
202 // TODO: defer this and attach dynamically
Brian Salomond17f6582017-07-19 18:28:58 -0400203 if (!fContext->resourceProvider()->attachStencilAttachment(tex->asRenderTarget())) {
Eric Karl5c779752017-05-08 12:02:07 -0700204 return nullptr;
205 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000206 }
bungeman6bd52842016-10-27 09:30:08 -0700207 return tex;
bsalomon@google.come269f212011-11-07 13:29:52 +0000208}
209
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400210sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
Greg Danielbcf612b2017-05-01 13:50:58 +0000211 if (!this->caps()->isConfigRenderable(backendRT.config(), backendRT.sampleCnt() > 0)) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800212 return nullptr;
213 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000214 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400215 return this->onWrapBackendRenderTarget(backendRT);
bsalomon@google.come269f212011-11-07 13:29:52 +0000216}
217
Greg Daniel7ef28f32017-04-20 16:41:55 +0000218sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000219 int sampleCnt) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800220 this->handleDirtyContext();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000221 if (!this->caps()->isConfigRenderable(tex.config(), sampleCnt > 0)) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800222 return nullptr;
223 }
224 int maxSize = this->caps()->maxTextureSize();
Greg Daniel7ef28f32017-04-20 16:41:55 +0000225 if (tex.width() > maxSize || tex.height() > maxSize) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800226 return nullptr;
227 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400228 return this->onWrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800229}
230
cdaltone2e71c22016-04-07 18:13:29 -0700231GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700232 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000233 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700234 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700235 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700236 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700237 }
cdalton397536c2016-03-25 12:15:03 -0700238 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800239}
240
Robert Phillipse3302df2017-04-24 07:31:02 -0400241std::unique_ptr<gr_instanced::OpAllocator> GrGpu::createInstancedRenderingAllocator() {
242 SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
243 return this->onCreateInstancedRenderingAllocator();
244}
245
csmartdaltone0d36292016-07-29 08:14:20 -0700246gr_instanced::InstancedRendering* GrGpu::createInstancedRendering() {
247 SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
248 return this->onCreateInstancedRendering();
249}
250
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400251bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
252 GrSurface* src, GrSurfaceOrigin srcOrigin,
253 const SkIRect& srcRect, const SkIPoint& dstPoint) {
Brian Salomondcbb9d92017-07-19 10:53:20 -0400254 GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
joshualitt1cbdcde2015-08-21 11:53:29 -0700255 SkASSERT(dst && src);
256 this->handleDirtyContext();
Brian Salomonbf7b6202016-11-11 16:08:03 -0500257 // We don't allow conversion between integer configs and float/fixed configs.
258 if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
259 return false;
260 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400261 return this->onCopySurface(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
joshualitt1cbdcde2015-08-21 11:53:29 -0700262}
263
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400264bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
265 int width, int height, size_t rowBytes,
bsalomonf0674512015-07-28 13:26:15 -0700266 GrPixelConfig readConfig, DrawPreference* drawPreference,
267 ReadPixelTempDrawInfo* tempDrawInfo) {
268 SkASSERT(drawPreference);
269 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500270 SkASSERT(srcSurface);
bsalomonf0674512015-07-28 13:26:15 -0700271 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
272
egdaniel3fe03272016-08-15 10:59:17 -0700273 // We currently do not support reading into the packed formats 565 or 4444 as they are not
274 // required to have read back support on all devices and backends.
275 if (kRGB_565_GrPixelConfig == readConfig || kRGBA_4444_GrPixelConfig == readConfig) {
276 return false;
277 }
278
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400279 if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, readConfig,
280 drawPreference, tempDrawInfo)) {
bsalomonf0674512015-07-28 13:26:15 -0700281 return false;
282 }
283
284 // Check to see if we're going to request that the caller draw when drawing is not possible.
285 if (!srcSurface->asTexture() ||
286 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
287 // If we don't have a fallback to a straight read then fail.
288 if (kRequireDraw_DrawPreference == *drawPreference) {
289 return false;
290 }
291 *drawPreference = kNoDraw_DrawPreference;
292 }
293
294 return true;
295}
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400296bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
297 int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700298 GrPixelConfig srcConfig, DrawPreference* drawPreference,
299 WritePixelTempDrawInfo* tempDrawInfo) {
300 SkASSERT(drawPreference);
301 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500302 SkASSERT(dstSurface);
bsalomonf0674512015-07-28 13:26:15 -0700303 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
304
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400305 if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700306 tempDrawInfo)) {
307 return false;
308 }
309
310 // Check to see if we're going to request that the caller draw when drawing is not possible.
311 if (!dstSurface->asRenderTarget() ||
312 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
313 // If we don't have a fallback to a straight upload then fail.
314 if (kRequireDraw_DrawPreference == *drawPreference ||
315 !this->caps()->isConfigTexturable(srcConfig)) {
316 return false;
317 }
318 *drawPreference = kNoDraw_DrawPreference;
319 }
320 return true;
321}
322
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400323bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000324 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000325 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000326 size_t rowBytes) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500327 SkASSERT(surface);
328
329 // We don't allow conversion between integer configs and float/fixed configs.
330 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
331 return false;
332 }
egdaniel6d901da2015-07-30 12:02:15 -0700333
egdaniel6d901da2015-07-30 12:02:15 -0700334 size_t bpp = GrBytesPerPixel(config);
335 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
336 &left, &top, &width, &height,
337 &buffer,
338 &rowBytes)) {
339 return false;
340 }
341
Brian Salomonbf7b6202016-11-11 16:08:03 -0500342 this->handleDirtyContext();
343
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400344 return this->onReadPixels(surface, origin,
egdaniel6d901da2015-07-30 12:02:15 -0700345 left, top, width, height,
346 config, buffer,
347 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000348}
349
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400350bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700351 int left, int top, int width, int height,
Robert Phillips590533f2017-07-11 14:22:35 -0400352 GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500353 SkASSERT(surface);
Robert Phillips590533f2017-07-11 14:22:35 -0400354 if (1 == mipLevelCount) {
Greg Daniel660cc992017-06-26 14:55:05 -0400355 // We require that if we are not mipped, then the write region is contained in the surface
356 SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
357 SkIRect bounds = SkIRect::MakeWH(surface->width(), surface->height());
358 if (!bounds.contains(subRect)) {
359 return false;
360 }
361 } else if (0 != left || 0 != top || width != surface->width() || height != surface->height()) {
362 // We require that if the texels are mipped, than the write region is the entire surface
363 return false;
364 }
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400365
Robert Phillips590533f2017-07-11 14:22:35 -0400366 for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800367 if (!texels[currentMipLevel].fPixels ) {
368 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800369 }
370 }
jvanverth2dc29942015-09-01 07:16:46 -0700371
Brian Salomonbf7b6202016-11-11 16:08:03 -0500372 // We don't allow conversion between integer configs and float/fixed configs.
373 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
374 return false;
375 }
376
bsalomon@google.com6f379512011-11-16 20:36:03 +0000377 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400378 if (this->onWritePixels(surface, origin, left, top, width, height, config,
379 texels, mipLevelCount)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700380 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
Robert Phillips590533f2017-07-11 14:22:35 -0400381 this->didWriteToSurface(surface, &rect, mipLevelCount);
bsalomonb12ea412015-02-02 21:19:50 -0800382 fStats.incTextureUploads();
383 return true;
384 }
385 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000386}
387
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400388bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
cblume55f2d2d2016-02-26 13:20:48 -0800389 int left, int top, int width, int height,
390 GrPixelConfig config, const void* buffer,
391 size_t rowBytes) {
Robert Phillips590533f2017-07-11 14:22:35 -0400392 GrMipLevel mipLevel = { buffer, rowBytes };
cblume55f2d2d2016-02-26 13:20:48 -0800393
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400394 return this->writePixels(surface, origin, left, top, width, height, config, &mipLevel, 1);
cblume55f2d2d2016-02-26 13:20:48 -0800395}
396
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400397bool GrGpu::transferPixels(GrTexture* texture,
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,
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400400 size_t offset, size_t rowBytes) {
cdalton397536c2016-03-25 12:15:03 -0700401 SkASSERT(transferBuffer);
jvanverth17aa0472016-01-05 10:41:27 -0800402
Brian Salomonbf7b6202016-11-11 16:08:03 -0500403 // We don't allow conversion between integer configs and float/fixed configs.
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400404 if (GrPixelConfigIsSint(texture->config()) != GrPixelConfigIsSint(config)) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500405 return false;
406 }
407
Greg Daniel660cc992017-06-26 14:55:05 -0400408 // We require that the write region is contained in the texture
409 SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
410 SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
411 if (!bounds.contains(subRect)) {
412 return false;
413 }
414
jvanverth17aa0472016-01-05 10:41:27 -0800415 this->handleDirtyContext();
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400416 if (this->onTransferPixels(texture, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700417 transferBuffer, offset, rowBytes)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700418 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
Jim Van Verth2e5eaf02017-06-21 15:55:46 -0400419 this->didWriteToSurface(texture, &rect);
jvanverth17aa0472016-01-05 10:41:27 -0800420 fStats.incTransfersToTexture();
jvanverth84741b32016-09-30 08:39:02 -0700421
jvanverth17aa0472016-01-05 10:41:27 -0800422 return true;
423 }
424 return false;
425}
426
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400427void GrGpu::resolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000428 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000429 this->handleDirtyContext();
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400430 this->onResolveRenderTarget(target, origin);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000431}
432
jvanverth900bd4a2016-04-29 13:53:12 -0700433void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
434 SkASSERT(surface);
435 // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
436 if (nullptr == bounds || !bounds->isEmpty()) {
437 if (GrRenderTarget* target = surface->asRenderTarget()) {
438 target->flagAsNeedingResolve(bounds);
439 }
440 GrTexture* texture = surface->asTexture();
441 if (texture && 1 == mipLevels) {
442 texture->texturePriv().dirtyMipMaps(true);
443 }
444 }
445}
446
csmartdaltonc633abb2016-11-01 08:55:55 -0700447const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400448 GrRenderTarget* rt = pipeline.renderTarget();
Brian Salomon154ce912017-05-17 10:40:02 -0400449 SkASSERT(rt->numStencilSamples() > 1);
csmartdalton0d28e572016-07-06 09:59:43 -0700450
csmartdaltonc633abb2016-11-01 08:55:55 -0700451 GrStencilSettings stencil;
452 if (pipeline.isStencilEnabled()) {
453 // TODO: attach stencil and create settings during render target flush.
454 SkASSERT(rt->renderTargetPriv().getStencilAttachment());
455 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
456 rt->renderTargetPriv().numStencilBits());
457 }
458
cdalton28f45b92016-03-07 13:58:26 -0800459 int effectiveSampleCnt;
csmartdalton0d28e572016-07-06 09:59:43 -0700460 SkSTArray<16, SkPoint, true> pattern;
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400461 this->onQueryMultisampleSpecs(rt, pipeline.proxy()->origin(), stencil,
462 &effectiveSampleCnt, &pattern);
Brian Salomon154ce912017-05-17 10:40:02 -0400463 SkASSERT(effectiveSampleCnt >= rt->numStencilSamples());
csmartdalton0d28e572016-07-06 09:59:43 -0700464
465 uint8_t id;
466 if (this->caps()->sampleLocationsSupport()) {
467 SkASSERT(pattern.count() == effectiveSampleCnt);
468 const auto& insertResult = fMultisampleSpecsIdMap.insert(
469 MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
470 id = insertResult.first->second;
471 if (insertResult.second) {
472 // This means the insert did not find the pattern in the map already, and therefore an
473 // actual insertion took place. (We don't expect to see many unique sample patterns.)
474 const SkPoint* sampleLocations = insertResult.first->first.begin();
475 SkASSERT(id == fMultisampleSpecs.count());
476 fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
477 }
478 } else {
479 id = effectiveSampleCnt;
480 for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
481 fMultisampleSpecs.emplace_back(i, i, nullptr);
482 }
cdalton28f45b92016-03-07 13:58:26 -0800483 }
csmartdalton0d28e572016-07-06 09:59:43 -0700484 SkASSERT(id > 0);
csmartdalton0d28e572016-07-06 09:59:43 -0700485
csmartdalton0d28e572016-07-06 09:59:43 -0700486 return fMultisampleSpecs[id];
cdalton28f45b92016-03-07 13:58:26 -0800487}
488
csmartdalton0d28e572016-07-06 09:59:43 -0700489bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
490 const SamplePattern& b) const {
491 if (a.count() != b.count()) {
492 return a.count() < b.count();
493 }
494 for (int i = 0; i < a.count(); ++i) {
495 // This doesn't have geometric meaning. We just need to define an ordering for std::map.
496 if (a[i].x() != b[i].x()) {
497 return a[i].x() < b[i].x();
498 }
499 if (a[i].y() != b[i].y()) {
500 return a[i].y() < b[i].y();
501 }
502 }
503 return false; // Equal.
504}
Greg Daniel51316782017-08-02 15:10:09 +0000505
506GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
507 GrBackendSemaphore backendSemaphores[]) {
508 if (this->caps()->fenceSyncSupport()) {
509 for (int i = 0; i < numSemaphores; ++i) {
510 sk_sp<GrSemaphore> semaphore;
511 if (backendSemaphores[i].isInitialized()) {
512 semaphore = fContext->resourceProvider()->wrapBackendSemaphore(
513 backendSemaphores[i], kBorrow_GrWrapOwnership);
514 } else {
515 semaphore = fContext->resourceProvider()->makeSemaphore(false);
516 }
517 this->insertSemaphore(semaphore, false);
518
519 if (!backendSemaphores[i].isInitialized()) {
520 semaphore->setBackendSemaphore(&backendSemaphores[i]);
521 }
522 }
523 }
524 this->onFinishFlush((numSemaphores > 0 && this->caps()->fenceSyncSupport()));
525 return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes
526 : GrSemaphoresSubmitted::kNo;
527}
Brian Osman71a18892017-08-10 10:23:25 -0400528
529void GrGpu::dumpJSON(SkJSONWriter* writer) const {
530 writer->beginObject();
531
532 // TODO: Is there anything useful in the base class to dump here?
533
534 this->onDumpJSON(writer);
535
536 writer->endObject();
537}