blob: 4880f6c7427bc9aaf245d776b7aaaafccda7f6bf [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"
csmartdaltonc633abb2016-11-01 08:55:55 -070022#include "GrStencilSettings.h"
egdaniel6d901da2015-07-30 12:02:15 -070023#include "GrSurfacePriv.h"
jvanverth900bd4a2016-04-29 13:53:12 -070024#include "GrTexturePriv.h"
halcanary4dbbd042016-06-07 17:21:10 -070025#include "SkMathPriv.h"
bsalomoncb8979d2015-05-05 09:51:38 -070026
egdaniel0e1853c2016-03-17 11:35:45 -070027GrMesh& GrMesh::operator =(const GrMesh& di) {
bsalomoncb8979d2015-05-05 09:51:38 -070028 fPrimitiveType = di.fPrimitiveType;
29 fStartVertex = di.fStartVertex;
30 fStartIndex = di.fStartIndex;
31 fVertexCount = di.fVertexCount;
32 fIndexCount = di.fIndexCount;
33
34 fInstanceCount = di.fInstanceCount;
35 fVerticesPerInstance = di.fVerticesPerInstance;
36 fIndicesPerInstance = di.fIndicesPerInstance;
bsalomone64eb572015-05-07 11:35:55 -070037 fMaxInstancesPerDraw = di.fMaxInstancesPerDraw;
bsalomoncb8979d2015-05-05 09:51:38 -070038
39 fVertexBuffer.reset(di.vertexBuffer());
40 fIndexBuffer.reset(di.indexBuffer());
41
42 return *this;
43}
bsalomon@google.com1c13c962011-02-14 16:51:21 +000044
bsalomon@google.comd302f142011-03-03 13:54:13 +000045////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000046
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000047GrGpu::GrGpu(GrContext* context)
joshualitt3322fa42014-11-07 08:48:51 -080048 : fResetTimestamp(kExpiredTimestamp+1)
bsalomon@google.com0a208a12013-06-28 18:57:35 +000049 , fResetBits(kAll_GrBackendState)
joshualitt3322fa42014-11-07 08:48:51 -080050 , fContext(context) {
csmartdalton0d28e572016-07-06 09:59:43 -070051 fMultisampleSpecs.emplace_back(0, 0, nullptr); // Index 0 is an invalid unique id.
reed@google.comac10a2d2010-12-22 21:39:39 +000052}
53
bsalomoned0bcad2015-05-04 10:36:42 -070054GrGpu::~GrGpu() {}
bsalomon1d89ddc2014-08-19 14:20:58 -070055
bsalomon6e2aad42016-04-01 11:54:31 -070056void GrGpu::disconnect(DisconnectType) {}
reed@google.comac10a2d2010-12-22 21:39:39 +000057
bsalomon@google.comd302f142011-03-03 13:54:13 +000058////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000059
Brian Salomon514baff2016-11-17 15:17:07 -050060bool GrGpu::makeCopyForTextureParams(int width, int height, const GrSamplerParams& textureParams,
Robert Phillips67c18d62017-01-20 12:44:06 -050061 GrTextureProducer::CopyParams* copyParams,
62 SkScalar scaleAdjust[2]) const {
bsalomon045802d2015-10-20 07:58:01 -070063 const GrCaps& caps = *this->caps();
64 if (textureParams.isTiled() && !caps.npotTextureTileSupport() &&
65 (!SkIsPow2(width) || !SkIsPow2(height))) {
Robert Phillips67c18d62017-01-20 12:44:06 -050066 SkASSERT(scaleAdjust);
bsalomon100b8f82015-10-28 08:37:44 -070067 copyParams->fWidth = GrNextPow2(width);
68 copyParams->fHeight = GrNextPow2(height);
Robert Phillips67c18d62017-01-20 12:44:06 -050069 scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
70 scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
bsalomon045802d2015-10-20 07:58:01 -070071 switch (textureParams.filterMode()) {
Brian Salomon514baff2016-11-17 15:17:07 -050072 case GrSamplerParams::kNone_FilterMode:
73 copyParams->fFilter = GrSamplerParams::kNone_FilterMode;
bsalomon045802d2015-10-20 07:58:01 -070074 break;
Brian Salomon514baff2016-11-17 15:17:07 -050075 case GrSamplerParams::kBilerp_FilterMode:
76 case GrSamplerParams::kMipMap_FilterMode:
bsalomon045802d2015-10-20 07:58:01 -070077 // We are only ever scaling up so no reason to ever indicate kMipMap.
Brian Salomon514baff2016-11-17 15:17:07 -050078 copyParams->fFilter = GrSamplerParams::kBilerp_FilterMode;
bsalomon045802d2015-10-20 07:58:01 -070079 break;
80 }
bsalomon100b8f82015-10-28 08:37:44 -070081 return true;
bsalomon045802d2015-10-20 07:58:01 -070082 }
bsalomon100b8f82015-10-28 08:37:44 -070083 return false;
bsalomon045802d2015-10-20 07:58:01 -070084}
85
egdanielcf614fd2015-04-22 13:58:58 -070086static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
egdanielb0e1be22015-04-22 13:27:39 -070087 // By default, GrRenderTargets are GL's normal orientation so that they
88 // can be drawn to by the outside world without the client having
89 // to render upside down.
90 if (kDefault_GrSurfaceOrigin == origin) {
91 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
92 } else {
93 return origin;
94 }
95}
96
cblume55f2d2d2016-02-26 13:20:48 -080097/**
98 * Prior to creating a texture, make sure the type of texture being created is
99 * supported by calling check_texture_creation_params.
100 *
101 * @param caps The capabilities of the GL device.
102 * @param desc The descriptor of the texture to create.
103 * @param isRT Indicates if the texture can be a render target.
104 */
105static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
bsalomone699d0c2016-03-09 06:25:15 -0800106 bool* isRT, const SkTArray<GrMipLevel>& texels) {
cblume55f2d2d2016-02-26 13:20:48 -0800107 if (!caps.isConfigTexturable(desc.fConfig)) {
108 return false;
robertphillips@google.comd3eb3362012-10-31 13:56:35 +0000109 }
krajcevski9c0e6292014-06-02 07:38:14 -0700110
Brian Salomonbf7b6202016-11-11 16:08:03 -0500111 if (GrPixelConfigIsSint(desc.fConfig) && texels.count() > 1) {
112 return false;
113 }
114
cblume55f2d2d2016-02-26 13:20:48 -0800115 *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
116 if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
117 return false;
commit-bot@chromium.org6b7938f2013-10-15 14:18:16 +0000118 }
robertphillips@google.comd3eb3362012-10-31 13:56:35 +0000119
robertphillips6e83ac72015-08-13 05:19:14 -0700120 // We currently do not support multisampled textures
cblume55f2d2d2016-02-26 13:20:48 -0800121 if (!*isRT && desc.fSampleCnt > 0) {
122 return false;
123 }
124
125 if (*isRT) {
126 int maxRTSize = caps.maxRenderTargetSize();
127 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
128 return false;
129 }
130 } else {
131 int maxSize = caps.maxTextureSize();
132 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
133 return false;
134 }
135 }
bsalomone699d0c2016-03-09 06:25:15 -0800136
137 for (int i = 0; i < texels.count(); ++i) {
138 if (!texels[i].fPixels) {
139 return false;
140 }
141 }
cblume55f2d2d2016-02-26 13:20:48 -0800142 return true;
143}
144
145GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
146 const SkTArray<GrMipLevel>& texels) {
147 GrSurfaceDesc desc = origDesc;
148
149 const GrCaps* caps = this->caps();
150 bool isRT = false;
bsalomone699d0c2016-03-09 06:25:15 -0800151 bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT, texels);
cblume55f2d2d2016-02-26 13:20:48 -0800152 if (!textureCreationParamsValid) {
halcanary96fcdcc2015-08-27 07:41:13 -0700153 return nullptr;
egdaniel8c9b6f12015-05-12 13:36:30 -0700154 }
155
cblume55f2d2d2016-02-26 13:20:48 -0800156 desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
157 // Attempt to catch un- or wrongly intialized sample counts;
egdanielb0e1be22015-04-22 13:27:39 -0700158 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
159
160 desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
161
cblume55f2d2d2016-02-26 13:20:48 -0800162 GrTexture* tex = nullptr;
cblume55f2d2d2016-02-26 13:20:48 -0800163
krajcevski9c0e6292014-06-02 07:38:14 -0700164 if (GrPixelConfigIsCompressed(desc.fConfig)) {
165 // We shouldn't be rendering into this
egdanielb0e1be22015-04-22 13:27:39 -0700166 SkASSERT(!isRT);
167 SkASSERT(0 == desc.fSampleCnt);
krajcevski9c0e6292014-06-02 07:38:14 -0700168
cblume55f2d2d2016-02-26 13:20:48 -0800169 if (!caps->npotTextureTileSupport() &&
tfarinaf9dae782014-06-06 06:35:28 -0700170 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
halcanary96fcdcc2015-08-27 07:41:13 -0700171 return nullptr;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000172 }
tfarinaf9dae782014-06-06 06:35:28 -0700173
krajcevski9c0e6292014-06-02 07:38:14 -0700174 this->handleDirtyContext();
kkinnunen2e6055b2016-04-22 01:48:29 -0700175 tex = this->onCreateCompressedTexture(desc, budgeted, texels);
krajcevski9c0e6292014-06-02 07:38:14 -0700176 } else {
177 this->handleDirtyContext();
kkinnunen2e6055b2016-04-22 01:48:29 -0700178 tex = this->onCreateTexture(desc, budgeted, texels);
bsalomondb558dd2015-01-23 13:19:00 -0800179 }
bsalomonb12ea412015-02-02 21:19:50 -0800180 if (tex) {
cblume55f2d2d2016-02-26 13:20:48 -0800181 if (!caps->reuseScratchTextures() && !isRT) {
182 tex->resourcePriv().removeScratchKey();
183 }
bsalomonb12ea412015-02-02 21:19:50 -0800184 fStats.incTextureCreates();
cblume55f2d2d2016-02-26 13:20:48 -0800185 if (!texels.empty()) {
186 if (texels[0].fPixels) {
187 fStats.incTextureUploads();
188 }
bsalomonb12ea412015-02-02 21:19:50 -0800189 }
egdaniel37535c92016-06-30 08:23:30 -0700190 // This is a current work around to get discards into newly created textures. Once we are in
191 // MDB world, we should remove this code a rely on the draw target having specified load
192 // operations.
193 if (isRT && texels.empty()) {
194 GrRenderTarget* rt = tex->asRenderTarget();
195 SkASSERT(rt);
196 rt->discard();
197 }
bsalomonb12ea412015-02-02 21:19:50 -0800198 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000199 return tex;
200}
201
bungeman6bd52842016-10-27 09:30:08 -0700202sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc,
203 GrWrapOwnership ownership) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000204 this->handleDirtyContext();
bsalomon5b30c6f2015-12-17 14:17:34 -0800205 if (!this->caps()->isConfigTexturable(desc.fConfig)) {
206 return nullptr;
207 }
208 if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) &&
209 !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
210 return nullptr;
211 }
ericrkf7b8b8a2016-02-24 14:49:51 -0800212 int maxSize = this->caps()->maxTextureSize();
213 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
214 return nullptr;
215 }
bungeman6bd52842016-10-27 09:30:08 -0700216 sk_sp<GrTexture> tex = this->onWrapBackendTexture(desc, ownership);
217 if (!tex) {
halcanary96fcdcc2015-08-27 07:41:13 -0700218 return nullptr;
bsalomon@google.coma14dd6d2012-01-03 21:08:12 +0000219 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000220 // TODO: defer this and attach dynamically
221 GrRenderTarget* tgt = tex->asRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700222 if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700223 return nullptr;
bsalomon@google.come269f212011-11-07 13:29:52 +0000224 }
bungeman6bd52842016-10-27 09:30:08 -0700225 return tex;
bsalomon@google.come269f212011-11-07 13:29:52 +0000226}
227
bungeman6bd52842016-10-27 09:30:08 -0700228sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
229 GrWrapOwnership ownership) {
bsalomon5b30c6f2015-12-17 14:17:34 -0800230 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
231 return nullptr;
232 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000233 this->handleDirtyContext();
stani89e6af62016-09-20 13:24:49 -0700234 return this->onWrapBackendRenderTarget(desc, ownership);
bsalomon@google.come269f212011-11-07 13:29:52 +0000235}
236
bungeman6bd52842016-10-27 09:30:08 -0700237sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800238 this->handleDirtyContext();
239 if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
240 return nullptr;
241 }
242 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
243 return nullptr;
244 }
245 int maxSize = this->caps()->maxTextureSize();
246 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
247 return nullptr;
248 }
kkinnunen49c4c222016-04-01 04:50:37 -0700249 return this->onWrapBackendTextureAsRenderTarget(desc);
ericrkf7b8b8a2016-02-24 14:49:51 -0800250}
251
cdaltone2e71c22016-04-07 18:13:29 -0700252GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700253 GrAccessPattern accessPattern, const void* data) {
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000254 this->handleDirtyContext();
cdalton1bf3e712016-04-19 10:00:02 -0700255 GrBuffer* buffer = this->onCreateBuffer(size, intendedType, accessPattern, data);
robertphillips1b8e1b52015-06-24 06:54:10 -0700256 if (!this->caps()->reuseScratchBuffers()) {
cdalton397536c2016-03-25 12:15:03 -0700257 buffer->resourcePriv().removeScratchKey();
robertphillips1b8e1b52015-06-24 06:54:10 -0700258 }
cdalton397536c2016-03-25 12:15:03 -0700259 return buffer;
jvanverth73063dc2015-12-03 09:15:47 -0800260}
261
csmartdaltone0d36292016-07-29 08:14:20 -0700262gr_instanced::InstancedRendering* GrGpu::createInstancedRendering() {
263 SkASSERT(GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport());
264 return this->onCreateInstancedRendering();
265}
266
joshualitt1cbdcde2015-08-21 11:53:29 -0700267bool GrGpu::copySurface(GrSurface* dst,
268 GrSurface* src,
269 const SkIRect& srcRect,
270 const SkIPoint& dstPoint) {
271 SkASSERT(dst && src);
272 this->handleDirtyContext();
Brian Salomonbf7b6202016-11-11 16:08:03 -0500273 // We don't allow conversion between integer configs and float/fixed configs.
274 if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
275 return false;
276 }
277 if (GrPixelConfigIsCompressed(dst->config())) {
278 return false;
279 }
joshualitt1cbdcde2015-08-21 11:53:29 -0700280 return this->onCopySurface(dst, src, srcRect, dstPoint);
281}
282
bsalomonf0674512015-07-28 13:26:15 -0700283bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
284 GrPixelConfig readConfig, DrawPreference* drawPreference,
285 ReadPixelTempDrawInfo* tempDrawInfo) {
286 SkASSERT(drawPreference);
287 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500288 SkASSERT(srcSurface);
bsalomonf0674512015-07-28 13:26:15 -0700289 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
290
Brian Salomonbf7b6202016-11-11 16:08:03 -0500291 // We don't allow conversion between integer configs and float/fixed configs.
292 if (GrPixelConfigIsSint(srcSurface->config()) != GrPixelConfigIsSint(readConfig)) {
293 return false;
294 }
295
egdaniel6d901da2015-07-30 12:02:15 -0700296 // We currently do not support reading into a compressed buffer
297 if (GrPixelConfigIsCompressed(readConfig)) {
298 return false;
299 }
300
egdaniel3fe03272016-08-15 10:59:17 -0700301 // We currently do not support reading into the packed formats 565 or 4444 as they are not
302 // required to have read back support on all devices and backends.
303 if (kRGB_565_GrPixelConfig == readConfig || kRGBA_4444_GrPixelConfig == readConfig) {
304 return false;
305 }
306
bsalomonf0674512015-07-28 13:26:15 -0700307 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
308 tempDrawInfo)) {
309 return false;
310 }
311
312 // Check to see if we're going to request that the caller draw when drawing is not possible.
313 if (!srcSurface->asTexture() ||
314 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
315 // If we don't have a fallback to a straight read then fail.
316 if (kRequireDraw_DrawPreference == *drawPreference) {
317 return false;
318 }
319 *drawPreference = kNoDraw_DrawPreference;
320 }
321
322 return true;
323}
cblumeed828002016-02-16 13:00:01 -0800324bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bsalomonf0674512015-07-28 13:26:15 -0700325 GrPixelConfig srcConfig, DrawPreference* drawPreference,
326 WritePixelTempDrawInfo* tempDrawInfo) {
327 SkASSERT(drawPreference);
328 SkASSERT(tempDrawInfo);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500329 SkASSERT(dstSurface);
bsalomonf0674512015-07-28 13:26:15 -0700330 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
331
jvanverth2dc29942015-09-01 07:16:46 -0700332 if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) &&
333 dstSurface->desc().fConfig != srcConfig) {
334 return false;
335 }
336
Brian Salomonbf7b6202016-11-11 16:08:03 -0500337 // We don't allow conversion between integer configs and float/fixed configs.
338 if (GrPixelConfigIsSint(dstSurface->config()) != GrPixelConfigIsSint(srcConfig)) {
339 return false;
340 }
341
bsalomonbabafcc2016-02-16 11:36:47 -0800342 if (SkToBool(dstSurface->asRenderTarget())) {
343 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) {
344 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
345 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
346 (width < dstSurface->width() || height < dstSurface->height())) {
347 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
348 }
bsalomonf0674512015-07-28 13:26:15 -0700349 }
350
cblumeed828002016-02-16 13:00:01 -0800351 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700352 tempDrawInfo)) {
353 return false;
354 }
355
356 // Check to see if we're going to request that the caller draw when drawing is not possible.
357 if (!dstSurface->asRenderTarget() ||
358 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
359 // If we don't have a fallback to a straight upload then fail.
360 if (kRequireDraw_DrawPreference == *drawPreference ||
361 !this->caps()->isConfigTexturable(srcConfig)) {
362 return false;
363 }
364 *drawPreference = kNoDraw_DrawPreference;
365 }
366 return true;
367}
368
bsalomon6cb3cbe2015-07-30 07:34:27 -0700369bool GrGpu::readPixels(GrSurface* surface,
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000370 int left, int top, int width, int height,
bsalomon@google.comc6980972011-11-02 19:57:21 +0000371 GrPixelConfig config, void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000372 size_t rowBytes) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500373 SkASSERT(surface);
374
375 // We don't allow conversion between integer configs and float/fixed configs.
376 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
377 return false;
378 }
egdaniel6d901da2015-07-30 12:02:15 -0700379
380 // We cannot read pixels into a compressed buffer
381 if (GrPixelConfigIsCompressed(config)) {
382 return false;
383 }
384
385 size_t bpp = GrBytesPerPixel(config);
386 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
387 &left, &top, &width, &height,
388 &buffer,
389 &rowBytes)) {
390 return false;
391 }
392
Brian Salomonbf7b6202016-11-11 16:08:03 -0500393 this->handleDirtyContext();
394
egdaniel6d901da2015-07-30 12:02:15 -0700395 return this->onReadPixels(surface,
396 left, top, width, height,
397 config, buffer,
398 rowBytes);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000399}
400
bsalomon6cb3cbe2015-07-30 07:34:27 -0700401bool GrGpu::writePixels(GrSurface* surface,
402 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800403 GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500404 SkASSERT(surface);
cblume55f2d2d2016-02-26 13:20:48 -0800405 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
bsalomone699d0c2016-03-09 06:25:15 -0800406 if (!texels[currentMipLevel].fPixels ) {
407 return false;
cblume55f2d2d2016-02-26 13:20:48 -0800408 }
409 }
jvanverth2dc29942015-09-01 07:16:46 -0700410
Brian Salomonbf7b6202016-11-11 16:08:03 -0500411 // We don't allow conversion between integer configs and float/fixed configs.
412 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
413 return false;
414 }
415
bsalomon@google.com6f379512011-11-16 20:36:03 +0000416 this->handleDirtyContext();
cblume55f2d2d2016-02-26 13:20:48 -0800417 if (this->onWritePixels(surface, left, top, width, height, config, texels)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700418 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
419 this->didWriteToSurface(surface, &rect, texels.count());
bsalomonb12ea412015-02-02 21:19:50 -0800420 fStats.incTextureUploads();
421 return true;
422 }
423 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000424}
425
cblume55f2d2d2016-02-26 13:20:48 -0800426bool GrGpu::writePixels(GrSurface* surface,
427 int left, int top, int width, int height,
428 GrPixelConfig config, const void* buffer,
429 size_t rowBytes) {
430 GrMipLevel mipLevel;
431 mipLevel.fPixels = buffer;
432 mipLevel.fRowBytes = rowBytes;
433 SkSTArray<1, GrMipLevel> texels;
434 texels.push_back(mipLevel);
435
436 return this->writePixels(surface, left, top, width, height, config, texels);
437}
438
jvanverthc3d706f2016-04-20 10:33:27 -0700439bool GrGpu::transferPixels(GrSurface* surface,
jvanverth17aa0472016-01-05 10:41:27 -0800440 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700441 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth84741b32016-09-30 08:39:02 -0700442 size_t offset, size_t rowBytes, GrFence* fence) {
cdalton397536c2016-03-25 12:15:03 -0700443 SkASSERT(transferBuffer);
jvanverth84741b32016-09-30 08:39:02 -0700444 SkASSERT(fence);
jvanverth17aa0472016-01-05 10:41:27 -0800445
Brian Salomonbf7b6202016-11-11 16:08:03 -0500446 // We don't allow conversion between integer configs and float/fixed configs.
447 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
448 return false;
449 }
450
jvanverth17aa0472016-01-05 10:41:27 -0800451 this->handleDirtyContext();
jvanverthc3d706f2016-04-20 10:33:27 -0700452 if (this->onTransferPixels(surface, left, top, width, height, config,
cdalton397536c2016-03-25 12:15:03 -0700453 transferBuffer, offset, rowBytes)) {
jvanverth900bd4a2016-04-29 13:53:12 -0700454 SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
455 this->didWriteToSurface(surface, &rect);
jvanverth17aa0472016-01-05 10:41:27 -0800456 fStats.incTransfersToTexture();
jvanverth84741b32016-09-30 08:39:02 -0700457
458 if (*fence) {
459 this->deleteFence(*fence);
460 }
461 *fence = this->insertFence();
462
jvanverth17aa0472016-01-05 10:41:27 -0800463 return true;
464 }
465 return false;
466}
467
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000468void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000469 SkASSERT(target);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000470 this->handleDirtyContext();
471 this->onResolveRenderTarget(target);
472}
473
jvanverth900bd4a2016-04-29 13:53:12 -0700474void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
475 SkASSERT(surface);
476 // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
477 if (nullptr == bounds || !bounds->isEmpty()) {
478 if (GrRenderTarget* target = surface->asRenderTarget()) {
479 target->flagAsNeedingResolve(bounds);
480 }
481 GrTexture* texture = surface->asTexture();
482 if (texture && 1 == mipLevels) {
483 texture->texturePriv().dirtyMipMaps(true);
484 }
485 }
486}
487
csmartdaltonc633abb2016-11-01 08:55:55 -0700488const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
489 GrRenderTarget* rt = pipeline.getRenderTarget();
csmartdalton0d28e572016-07-06 09:59:43 -0700490 SkASSERT(rt->desc().fSampleCnt > 1);
491
csmartdaltonc633abb2016-11-01 08:55:55 -0700492 GrStencilSettings stencil;
493 if (pipeline.isStencilEnabled()) {
494 // TODO: attach stencil and create settings during render target flush.
495 SkASSERT(rt->renderTargetPriv().getStencilAttachment());
496 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
497 rt->renderTargetPriv().numStencilBits());
498 }
499
cdalton28f45b92016-03-07 13:58:26 -0800500 int effectiveSampleCnt;
csmartdalton0d28e572016-07-06 09:59:43 -0700501 SkSTArray<16, SkPoint, true> pattern;
csmartdaltonc25c5d72016-11-01 07:03:59 -0700502 this->onQueryMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern);
csmartdalton0d28e572016-07-06 09:59:43 -0700503 SkASSERT(effectiveSampleCnt >= rt->desc().fSampleCnt);
504
505 uint8_t id;
506 if (this->caps()->sampleLocationsSupport()) {
507 SkASSERT(pattern.count() == effectiveSampleCnt);
508 const auto& insertResult = fMultisampleSpecsIdMap.insert(
509 MultisampleSpecsIdMap::value_type(pattern, SkTMin(fMultisampleSpecs.count(), 255)));
510 id = insertResult.first->second;
511 if (insertResult.second) {
512 // This means the insert did not find the pattern in the map already, and therefore an
513 // actual insertion took place. (We don't expect to see many unique sample patterns.)
514 const SkPoint* sampleLocations = insertResult.first->first.begin();
515 SkASSERT(id == fMultisampleSpecs.count());
516 fMultisampleSpecs.emplace_back(id, effectiveSampleCnt, sampleLocations);
517 }
518 } else {
519 id = effectiveSampleCnt;
520 for (int i = fMultisampleSpecs.count(); i <= id; ++i) {
521 fMultisampleSpecs.emplace_back(i, i, nullptr);
522 }
cdalton28f45b92016-03-07 13:58:26 -0800523 }
csmartdalton0d28e572016-07-06 09:59:43 -0700524 SkASSERT(id > 0);
csmartdalton0d28e572016-07-06 09:59:43 -0700525
csmartdalton0d28e572016-07-06 09:59:43 -0700526 return fMultisampleSpecs[id];
cdalton28f45b92016-03-07 13:58:26 -0800527}
528
csmartdalton0d28e572016-07-06 09:59:43 -0700529bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a,
530 const SamplePattern& b) const {
531 if (a.count() != b.count()) {
532 return a.count() < b.count();
533 }
534 for (int i = 0; i < a.count(); ++i) {
535 // This doesn't have geometric meaning. We just need to define an ordering for std::map.
536 if (a[i].x() != b[i].x()) {
537 return a[i].x() < b[i].x();
538 }
539 if (a[i].y() != b[i].y()) {
540 return a[i].y() < b[i].y();
541 }
542 }
543 return false; // Equal.
544}