1 /* 2 * 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. 6 */ 7 8 9 #include "GrGpu.h" 10 11 #include "GrCaps.h" 12 #include "GrContext.h" 13 #include "GrGpuResourcePriv.h" 14 #include "GrIndexBuffer.h" 15 #include "GrPathRendering.h" 16 #include "GrPipeline.h" 17 #include "GrResourceCache.h" 18 #include "GrResourceProvider.h" 19 #include "GrRenderTargetPriv.h" 20 #include "GrStencilAttachment.h" 21 #include "GrSurfacePriv.h" 22 #include "GrTransferBuffer.h" 23 #include "GrVertexBuffer.h" 24 #include "GrVertices.h" 25 26 GrVertices& GrVertices::operator =(const GrVertices& di) { 27 fPrimitiveType = di.fPrimitiveType; 28 fStartVertex = di.fStartVertex; 29 fStartIndex = di.fStartIndex; 30 fVertexCount = di.fVertexCount; 31 fIndexCount = di.fIndexCount; 32 33 fInstanceCount = di.fInstanceCount; 34 fVerticesPerInstance = di.fVerticesPerInstance; 35 fIndicesPerInstance = di.fIndicesPerInstance; 36 fMaxInstancesPerDraw = di.fMaxInstancesPerDraw; 37 38 fVertexBuffer.reset(di.vertexBuffer()); 39 fIndexBuffer.reset(di.indexBuffer()); 40 41 return *this; 42 } 43 44 //////////////////////////////////////////////////////////////////////////////// 45 46 GrGpu::GrGpu(GrContext* context) 47 : fResetTimestamp(kExpiredTimestamp+1) 48 , fResetBits(kAll_GrBackendState) 49 , fContext(context) { 50 } 51 52 GrGpu::~GrGpu() {} 53 54 void GrGpu::contextAbandoned() {} 55 56 //////////////////////////////////////////////////////////////////////////////// 57 58 bool GrGpu::makeCopyForTextureParams(int width, int height, const GrTextureParams& textureParams, 59 GrTextureProducer::CopyParams* copyParams) const { 60 const GrCaps& caps = *this->caps(); 61 if (textureParams.isTiled() && !caps.npotTextureTileSupport() && 62 (!SkIsPow2(width) || !SkIsPow2(height))) { 63 copyParams->fWidth = GrNextPow2(width); 64 copyParams->fHeight = GrNextPow2(height); 65 switch (textureParams.filterMode()) { 66 case GrTextureParams::kNone_FilterMode: 67 copyParams->fFilter = GrTextureParams::kNone_FilterMode; 68 break; 69 case GrTextureParams::kBilerp_FilterMode: 70 case GrTextureParams::kMipMap_FilterMode: 71 // We are only ever scaling up so no reason to ever indicate kMipMap. 72 copyParams->fFilter = GrTextureParams::kBilerp_FilterMode; 73 break; 74 } 75 return true; 76 } 77 return false; 78 } 79 80 static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) { 81 // By default, GrRenderTargets are GL's normal orientation so that they 82 // can be drawn to by the outside world without the client having 83 // to render upside down. 84 if (kDefault_GrSurfaceOrigin == origin) { 85 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; 86 } else { 87 return origin; 88 } 89 } 90 91 GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted, 92 const void* srcData, size_t rowBytes) { 93 GrSurfaceDesc desc = origDesc; 94 95 if (!this->caps()->isConfigTexturable(desc.fConfig)) { 96 return nullptr; 97 } 98 99 bool isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); 100 if (isRT && !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 101 return nullptr; 102 } 103 104 // We currently do not support multisampled textures 105 if (!isRT && desc.fSampleCnt > 0) { 106 return nullptr; 107 } 108 109 GrTexture *tex = nullptr; 110 111 if (isRT) { 112 int maxRTSize = this->caps()->maxRenderTargetSize(); 113 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) { 114 return nullptr; 115 } 116 } else { 117 int maxSize = this->caps()->maxTextureSize(); 118 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 119 return nullptr; 120 } 121 } 122 123 GrGpuResource::LifeCycle lifeCycle = SkBudgeted::kYes == budgeted ? 124 GrGpuResource::kCached_LifeCycle : 125 GrGpuResource::kUncached_LifeCycle; 126 127 desc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); 128 // Attempt to catch un- or wrongly initialized sample counts; 129 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); 130 131 desc.fOrigin = resolve_origin(desc.fOrigin, isRT); 132 133 if (GrPixelConfigIsCompressed(desc.fConfig)) { 134 // We shouldn't be rendering into this 135 SkASSERT(!isRT); 136 SkASSERT(0 == desc.fSampleCnt); 137 138 if (!this->caps()->npotTextureTileSupport() && 139 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) { 140 return nullptr; 141 } 142 143 this->handleDirtyContext(); 144 tex = this->onCreateCompressedTexture(desc, lifeCycle, srcData); 145 } else { 146 this->handleDirtyContext(); 147 tex = this->onCreateTexture(desc, lifeCycle, srcData, rowBytes); 148 } 149 if (!this->caps()->reuseScratchTextures() && !isRT) { 150 tex->resourcePriv().removeScratchKey(); 151 } 152 if (tex) { 153 fStats.incTextureCreates(); 154 if (srcData) { 155 fStats.incTextureUploads(); 156 } 157 } 158 return tex; 159 } 160 161 GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) { 162 this->handleDirtyContext(); 163 if (!this->caps()->isConfigTexturable(desc.fConfig)) { 164 return nullptr; 165 } 166 if ((desc.fFlags & kRenderTarget_GrBackendTextureFlag) && 167 !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 168 return nullptr; 169 } 170 int maxSize = this->caps()->maxTextureSize(); 171 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 172 return nullptr; 173 } 174 GrTexture* tex = this->onWrapBackendTexture(desc, ownership); 175 if (nullptr == tex) { 176 return nullptr; 177 } 178 // TODO: defer this and attach dynamically 179 GrRenderTarget* tgt = tex->asRenderTarget(); 180 if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) { 181 tex->unref(); 182 return nullptr; 183 } else { 184 return tex; 185 } 186 } 187 188 GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc, 189 GrWrapOwnership ownership) { 190 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 191 return nullptr; 192 } 193 this->handleDirtyContext(); 194 return this->onWrapBackendRenderTarget(desc, ownership); 195 } 196 197 GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc, 198 GrWrapOwnership ownership) { 199 this->handleDirtyContext(); 200 if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) { 201 return nullptr; 202 } 203 if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 204 return nullptr; 205 } 206 int maxSize = this->caps()->maxTextureSize(); 207 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 208 return nullptr; 209 } 210 return this->onWrapBackendTextureAsRenderTarget(desc, ownership); 211 } 212 213 GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) { 214 this->handleDirtyContext(); 215 GrVertexBuffer* vb = this->onCreateVertexBuffer(size, dynamic); 216 if (!this->caps()->reuseScratchBuffers()) { 217 vb->resourcePriv().removeScratchKey(); 218 } 219 return vb; 220 } 221 222 GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) { 223 this->handleDirtyContext(); 224 GrIndexBuffer* ib = this->onCreateIndexBuffer(size, dynamic); 225 if (!this->caps()->reuseScratchBuffers()) { 226 ib->resourcePriv().removeScratchKey(); 227 } 228 return ib; 229 } 230 231 GrTransferBuffer* GrGpu::createTransferBuffer(size_t size, TransferType type) { 232 this->handleDirtyContext(); 233 GrTransferBuffer* tb = this->onCreateTransferBuffer(size, type); 234 return tb; 235 } 236 237 void GrGpu::clear(const SkIRect& rect, 238 GrColor color, 239 GrRenderTarget* renderTarget) { 240 SkASSERT(renderTarget); 241 SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect)); 242 this->handleDirtyContext(); 243 this->onClear(renderTarget, rect, color); 244 } 245 246 void GrGpu::clearStencilClip(const SkIRect& rect, 247 bool insideClip, 248 GrRenderTarget* renderTarget) { 249 SkASSERT(renderTarget); 250 this->handleDirtyContext(); 251 this->onClearStencilClip(renderTarget, rect, insideClip); 252 } 253 254 bool GrGpu::copySurface(GrSurface* dst, 255 GrSurface* src, 256 const SkIRect& srcRect, 257 const SkIPoint& dstPoint) { 258 SkASSERT(dst && src); 259 this->handleDirtyContext(); 260 return this->onCopySurface(dst, src, srcRect, dstPoint); 261 } 262 263 bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, 264 GrPixelConfig readConfig, DrawPreference* drawPreference, 265 ReadPixelTempDrawInfo* tempDrawInfo) { 266 SkASSERT(drawPreference); 267 SkASSERT(tempDrawInfo); 268 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); 269 270 // We currently do not support reading into a compressed buffer 271 if (GrPixelConfigIsCompressed(readConfig)) { 272 return false; 273 } 274 275 if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference, 276 tempDrawInfo)) { 277 return false; 278 } 279 280 // Check to see if we're going to request that the caller draw when drawing is not possible. 281 if (!srcSurface->asTexture() || 282 !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) { 283 // If we don't have a fallback to a straight read then fail. 284 if (kRequireDraw_DrawPreference == *drawPreference) { 285 return false; 286 } 287 *drawPreference = kNoDraw_DrawPreference; 288 } 289 290 return true; 291 } 292 bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height, 293 GrPixelConfig srcConfig, DrawPreference* drawPreference, 294 WritePixelTempDrawInfo* tempDrawInfo) { 295 SkASSERT(drawPreference); 296 SkASSERT(tempDrawInfo); 297 SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); 298 299 if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) && 300 dstSurface->desc().fConfig != srcConfig) { 301 return false; 302 } 303 304 if (SkToBool(dstSurface->asRenderTarget())) { 305 if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) { 306 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); 307 } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() && 308 (width < dstSurface->width() || height < dstSurface->height())) { 309 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); 310 } 311 } 312 313 if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference, 314 tempDrawInfo)) { 315 return false; 316 } 317 318 // Check to see if we're going to request that the caller draw when drawing is not possible. 319 if (!dstSurface->asRenderTarget() || 320 !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) { 321 // If we don't have a fallback to a straight upload then fail. 322 if (kRequireDraw_DrawPreference == *drawPreference || 323 !this->caps()->isConfigTexturable(srcConfig)) { 324 return false; 325 } 326 *drawPreference = kNoDraw_DrawPreference; 327 } 328 return true; 329 } 330 331 bool GrGpu::readPixels(GrSurface* surface, 332 int left, int top, int width, int height, 333 GrPixelConfig config, void* buffer, 334 size_t rowBytes) { 335 this->handleDirtyContext(); 336 337 // We cannot read pixels into a compressed buffer 338 if (GrPixelConfigIsCompressed(config)) { 339 return false; 340 } 341 342 size_t bpp = GrBytesPerPixel(config); 343 if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp, 344 &left, &top, &width, &height, 345 &buffer, 346 &rowBytes)) { 347 return false; 348 } 349 350 return this->onReadPixels(surface, 351 left, top, width, height, 352 config, buffer, 353 rowBytes); 354 } 355 356 bool GrGpu::writePixels(GrSurface* surface, 357 int left, int top, int width, int height, 358 GrPixelConfig config, const void* buffer, 359 size_t rowBytes) { 360 if (!buffer || !surface) { 361 return false; 362 } 363 364 this->handleDirtyContext(); 365 if (this->onWritePixels(surface, left, top, width, height, config, buffer, rowBytes)) { 366 fStats.incTextureUploads(); 367 return true; 368 } 369 return false; 370 } 371 372 bool GrGpu::transferPixels(GrSurface* surface, 373 int left, int top, int width, int height, 374 GrPixelConfig config, GrTransferBuffer* buffer, 375 size_t offset, size_t rowBytes) { 376 SkASSERT(buffer); 377 378 this->handleDirtyContext(); 379 if (this->onTransferPixels(surface, left, top, width, height, config, 380 buffer, offset, rowBytes)) { 381 fStats.incTransfersToTexture(); 382 return true; 383 } 384 return false; 385 } 386 387 void GrGpu::resolveRenderTarget(GrRenderTarget* target) { 388 SkASSERT(target); 389 this->handleDirtyContext(); 390 this->onResolveRenderTarget(target); 391 } 392 393 //////////////////////////////////////////////////////////////////////////////// 394 395 void GrGpu::draw(const DrawArgs& args, const GrVertices& vertices) { 396 this->handleDirtyContext(); 397 if (GrXferBarrierType barrierType = args.fPipeline->xferBarrierType(*this->caps())) { 398 this->xferBarrier(args.fPipeline->getRenderTarget(), barrierType); 399 } 400 401 GrVertices::Iterator iter; 402 const GrNonInstancedVertices* verts = iter.init(vertices); 403 do { 404 this->onDraw(args, *verts); 405 fStats.incNumDraws(); 406 } while ((verts = iter.next())); 407 } 408 409