GrGpu.cpp revision e40d39725908d99d255496025411e5c9ca32663e
1 2/* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "GrGpu.h" 11 12#include "GrContext.h" 13#include "GrDrawTargetCaps.h" 14#include "GrGpuResourcePriv.h" 15#include "GrIndexBuffer.h" 16#include "GrResourceCache.h" 17#include "GrRenderTargetPriv.h" 18#include "GrStencilAttachment.h" 19#include "GrVertexBuffer.h" 20#include "GrVertices.h" 21 22GrVertices& GrVertices::operator =(const GrVertices& di) { 23 fPrimitiveType = di.fPrimitiveType; 24 fStartVertex = di.fStartVertex; 25 fStartIndex = di.fStartIndex; 26 fVertexCount = di.fVertexCount; 27 fIndexCount = di.fIndexCount; 28 29 fInstanceCount = di.fInstanceCount; 30 fVerticesPerInstance = di.fVerticesPerInstance; 31 fIndicesPerInstance = di.fIndicesPerInstance; 32 33 fVertexBuffer.reset(di.vertexBuffer()); 34 fIndexBuffer.reset(di.indexBuffer()); 35 36 return *this; 37} 38 39//////////////////////////////////////////////////////////////////////////////// 40 41GrGpu::GrGpu(GrContext* context) 42 : fResetTimestamp(kExpiredTimestamp+1) 43 , fResetBits(kAll_GrBackendState) 44 , fGpuTraceMarkerCount(0) 45 , fContext(context) { 46} 47 48GrGpu::~GrGpu() {} 49 50void GrGpu::contextAbandoned() {} 51 52//////////////////////////////////////////////////////////////////////////////// 53 54static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) { 55 // By default, GrRenderTargets are GL's normal orientation so that they 56 // can be drawn to by the outside world without the client having 57 // to render upside down. 58 if (kDefault_GrSurfaceOrigin == origin) { 59 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; 60 } else { 61 return origin; 62 } 63} 64 65GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, bool budgeted, 66 const void* srcData, size_t rowBytes) { 67 GrSurfaceDesc desc = origDesc; 68 69 if (!this->caps()->isConfigTexturable(desc.fConfig)) { 70 return NULL; 71 } 72 73 bool isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); 74 if (isRT && !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 75 return NULL; 76 } 77 78 GrTexture *tex = NULL; 79 80 if (isRT) { 81 int maxRTSize = this->caps()->maxRenderTargetSize(); 82 if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) { 83 return NULL; 84 } 85 } else { 86 int maxSize = this->caps()->maxTextureSize(); 87 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 88 return NULL; 89 } 90 } 91 92 GrGpuResource::LifeCycle lifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle : 93 GrGpuResource::kUncached_LifeCycle; 94 95 desc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); 96 // Attempt to catch un- or wrongly initialized sample counts; 97 SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); 98 99 desc.fOrigin = resolve_origin(desc.fOrigin, isRT); 100 101 if (GrPixelConfigIsCompressed(desc.fConfig)) { 102 // We shouldn't be rendering into this 103 SkASSERT(!isRT); 104 SkASSERT(0 == desc.fSampleCnt); 105 106 if (!this->caps()->npotTextureTileSupport() && 107 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) { 108 return NULL; 109 } 110 111 this->handleDirtyContext(); 112 tex = this->onCreateCompressedTexture(desc, lifeCycle, srcData); 113 } else { 114 this->handleDirtyContext(); 115 tex = this->onCreateTexture(desc, lifeCycle, srcData, rowBytes); 116 } 117 if (!this->caps()->reuseScratchTextures() && !isRT) { 118 tex->resourcePriv().removeScratchKey(); 119 } 120 if (tex) { 121 fStats.incTextureCreates(); 122 if (srcData) { 123 fStats.incTextureUploads(); 124 } 125 } 126 return tex; 127} 128 129bool GrGpu::attachStencilAttachmentToRenderTarget(GrRenderTarget* rt) { 130 SkASSERT(NULL == rt->renderTargetPriv().getStencilAttachment()); 131 GrUniqueKey sbKey; 132 133 int width = rt->width(); 134 int height = rt->height(); 135#if 0 136 if (this->caps()->oversizedStencilSupport()) { 137 width = SkNextPow2(width); 138 height = SkNextPow2(height); 139 } 140#endif 141 142 GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numSamples(), &sbKey); 143 SkAutoTUnref<GrStencilAttachment> sb(static_cast<GrStencilAttachment*>( 144 this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey))); 145 if (sb) { 146 if (this->attachStencilAttachmentToRenderTarget(sb, rt)) { 147 rt->renderTargetPriv().didAttachStencilAttachment(sb); 148 return true; 149 } 150 return false; 151 } 152 if (this->createStencilAttachmentForRenderTarget(rt, width, height)) { 153 // Right now we're clearing the stencil buffer here after it is 154 // attached to an RT for the first time. When we start matching 155 // stencil buffers with smaller color targets this will no longer 156 // be correct because it won't be guaranteed to clear the entire 157 // sb. 158 // We used to clear down in the GL subclass using a special purpose 159 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported 160 // FBO status. 161 this->clearStencil(rt); 162 GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment(); 163 sb->resourcePriv().setUniqueKey(sbKey); 164 return true; 165 } else { 166 return false; 167 } 168} 169 170GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc) { 171 this->handleDirtyContext(); 172 GrTexture* tex = this->onWrapBackendTexture(desc); 173 if (NULL == tex) { 174 return NULL; 175 } 176 // TODO: defer this and attach dynamically 177 GrRenderTarget* tgt = tex->asRenderTarget(); 178 if (tgt && !this->attachStencilAttachmentToRenderTarget(tgt)) { 179 tex->unref(); 180 return NULL; 181 } else { 182 return tex; 183 } 184} 185 186GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) { 187 this->handleDirtyContext(); 188 return this->onWrapBackendRenderTarget(desc); 189} 190 191GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) { 192 this->handleDirtyContext(); 193 return this->onCreateVertexBuffer(size, dynamic); 194} 195 196GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) { 197 this->handleDirtyContext(); 198 return this->onCreateIndexBuffer(size, dynamic); 199} 200 201void GrGpu::clear(const SkIRect* rect, 202 GrColor color, 203 bool canIgnoreRect, 204 GrRenderTarget* renderTarget) { 205 SkASSERT(renderTarget); 206 this->handleDirtyContext(); 207 this->onClear(renderTarget, rect, color, canIgnoreRect); 208} 209 210void GrGpu::clearStencilClip(const SkIRect& rect, 211 bool insideClip, 212 GrRenderTarget* renderTarget) { 213 SkASSERT(renderTarget); 214 this->handleDirtyContext(); 215 this->onClearStencilClip(renderTarget, rect, insideClip); 216} 217 218bool GrGpu::readPixels(GrRenderTarget* target, 219 int left, int top, int width, int height, 220 GrPixelConfig config, void* buffer, 221 size_t rowBytes) { 222 this->handleDirtyContext(); 223 return this->onReadPixels(target, left, top, width, height, 224 config, buffer, rowBytes); 225} 226 227bool GrGpu::writeTexturePixels(GrTexture* texture, 228 int left, int top, int width, int height, 229 GrPixelConfig config, const void* buffer, 230 size_t rowBytes) { 231 this->handleDirtyContext(); 232 if (this->onWriteTexturePixels(texture, left, top, width, height, 233 config, buffer, rowBytes)) { 234 fStats.incTextureUploads(); 235 return true; 236 } 237 return false; 238} 239 240void GrGpu::resolveRenderTarget(GrRenderTarget* target) { 241 SkASSERT(target); 242 this->handleDirtyContext(); 243 this->onResolveRenderTarget(target); 244} 245 246typedef GrTraceMarkerSet::Iter TMIter; 247void GrGpu::saveActiveTraceMarkers() { 248 if (this->caps()->gpuTracingSupport()) { 249 SkASSERT(0 == fStoredTraceMarkers.count()); 250 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 251 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 252 this->removeGpuTraceMarker(&(*iter)); 253 } 254 } 255} 256 257void GrGpu::restoreActiveTraceMarkers() { 258 if (this->caps()->gpuTracingSupport()) { 259 SkASSERT(0 == fActiveTraceMarkers.count()); 260 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 261 this->addGpuTraceMarker(&(*iter)); 262 } 263 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 264 this->fStoredTraceMarkers.remove(*iter); 265 } 266 } 267} 268 269void GrGpu::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 270 if (this->caps()->gpuTracingSupport()) { 271 SkASSERT(fGpuTraceMarkerCount >= 0); 272 this->fActiveTraceMarkers.add(*marker); 273 this->didAddGpuTraceMarker(); 274 ++fGpuTraceMarkerCount; 275 } 276} 277 278void GrGpu::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 279 if (this->caps()->gpuTracingSupport()) { 280 SkASSERT(fGpuTraceMarkerCount >= 1); 281 this->fActiveTraceMarkers.remove(*marker); 282 this->didRemoveGpuTraceMarker(); 283 --fGpuTraceMarkerCount; 284 } 285} 286 287//////////////////////////////////////////////////////////////////////////////// 288 289void GrGpu::draw(const DrawArgs& args, const GrVertices& vertices) { 290 this->handleDirtyContext(); 291 this->onDraw(args, vertices); 292} 293 294void GrGpu::stencilPath(const GrPath* path, const StencilPathState& state) { 295 this->handleDirtyContext(); 296 this->onStencilPath(path, state); 297} 298 299void GrGpu::drawPath(const DrawArgs& args, 300 const GrPath* path, 301 const GrStencilSettings& stencilSettings) { 302 this->handleDirtyContext(); 303 this->onDrawPath(args, path, stencilSettings); 304} 305 306void GrGpu::drawPaths(const DrawArgs& args, 307 const GrPathRange* pathRange, 308 const void* indices, 309 GrDrawTarget::PathIndexType indexType, 310 const float transformValues[], 311 GrDrawTarget::PathTransformType transformType, 312 int count, 313 const GrStencilSettings& stencilSettings) { 314 this->handleDirtyContext(); 315 pathRange->willDrawPaths(indices, indexType, count); 316 this->onDrawPaths(args, pathRange, indices, indexType, transformValues, 317 transformType, count, stencilSettings); 318} 319