GrGpu.cpp revision d95263c60e1c3b9e337d777d6f3cf286c1dc43f6
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 "GrBufferAllocPool.h" 13#include "GrContext.h" 14#include "GrDrawTargetCaps.h" 15#include "GrIndexBuffer.h" 16#include "GrResourceCache2.h" 17#include "GrStencilBuffer.h" 18#include "GrVertexBuffer.h" 19 20//////////////////////////////////////////////////////////////////////////////// 21 22GrGpu::GrGpu(GrContext* context) 23 : fResetTimestamp(kExpiredTimestamp+1) 24 , fResetBits(kAll_GrBackendState) 25 , fQuadIndexBuffer(NULL) 26 , fContext(context) { 27} 28 29GrGpu::~GrGpu() { 30 SkSafeSetNull(fQuadIndexBuffer); 31} 32 33void GrGpu::contextAbandoned() {} 34 35//////////////////////////////////////////////////////////////////////////////// 36 37GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc, 38 const void* srcData, size_t rowBytes) { 39 if (!this->caps()->isConfigTexturable(desc.fConfig)) { 40 return NULL; 41 } 42 43 if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) && 44 !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { 45 return NULL; 46 } 47 48 GrTexture *tex = NULL; 49 if (GrPixelConfigIsCompressed(desc.fConfig)) { 50 // We shouldn't be rendering into this 51 SkASSERT((desc.fFlags & kRenderTarget_GrSurfaceFlag) == 0); 52 53 if (!this->caps()->npotTextureTileSupport() && 54 (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) { 55 return NULL; 56 } 57 58 this->handleDirtyContext(); 59 tex = this->onCreateCompressedTexture(desc, srcData); 60 } else { 61 this->handleDirtyContext(); 62 tex = this->onCreateTexture(desc, srcData, rowBytes); 63 if (tex && 64 (kRenderTarget_GrSurfaceFlag & desc.fFlags) && 65 !(kNoStencil_GrSurfaceFlag & desc.fFlags)) { 66 SkASSERT(tex->asRenderTarget()); 67 // TODO: defer this and attach dynamically 68 if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) { 69 tex->unref(); 70 return NULL; 71 } 72 } 73 } 74 return tex; 75} 76 77bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) { 78 SkASSERT(NULL == rt->getStencilBuffer()); 79 GrResourceKey sbKey = GrStencilBuffer::ComputeKey(rt->width(), rt->height(), rt->numSamples()); 80 SkAutoTUnref<GrStencilBuffer> sb(static_cast<GrStencilBuffer*>( 81 this->getContext()->getResourceCache2()->findAndRefScratchResource(sbKey))); 82 if (sb) { 83 rt->setStencilBuffer(sb); 84 bool attached = this->attachStencilBufferToRenderTarget(sb, rt); 85 if (!attached) { 86 rt->setStencilBuffer(NULL); 87 } 88 return attached; 89 } 90 if (this->createStencilBufferForRenderTarget(rt, rt->width(), rt->height())) { 91 // Right now we're clearing the stencil buffer here after it is 92 // attached to an RT for the first time. When we start matching 93 // stencil buffers with smaller color targets this will no longer 94 // be correct because it won't be guaranteed to clear the entire 95 // sb. 96 // We used to clear down in the GL subclass using a special purpose 97 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported 98 // FBO status. 99 this->clearStencil(rt); 100 return true; 101 } else { 102 return false; 103 } 104} 105 106GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc) { 107 this->handleDirtyContext(); 108 GrTexture* tex = this->onWrapBackendTexture(desc); 109 if (NULL == tex) { 110 return NULL; 111 } 112 // TODO: defer this and attach dynamically 113 GrRenderTarget* tgt = tex->asRenderTarget(); 114 if (tgt && 115 !this->attachStencilBufferToRenderTarget(tgt)) { 116 tex->unref(); 117 return NULL; 118 } else { 119 return tex; 120 } 121} 122 123GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) { 124 this->handleDirtyContext(); 125 return this->onWrapBackendRenderTarget(desc); 126} 127 128GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) { 129 this->handleDirtyContext(); 130 return this->onCreateVertexBuffer(size, dynamic); 131} 132 133GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) { 134 this->handleDirtyContext(); 135 return this->onCreateIndexBuffer(size, dynamic); 136} 137 138GrIndexBuffer* GrGpu::createInstancedIndexBuffer(const uint16_t* pattern, 139 int patternSize, 140 int reps, 141 int vertCount, 142 bool isDynamic) { 143 size_t bufferSize = patternSize * reps * sizeof(uint16_t); 144 GrGpu* me = const_cast<GrGpu*>(this); 145 GrIndexBuffer* buffer = me->createIndexBuffer(bufferSize, isDynamic); 146 if (buffer) { 147 uint16_t* data = (uint16_t*) buffer->map(); 148 bool useTempData = (NULL == data); 149 if (useTempData) { 150 data = SkNEW_ARRAY(uint16_t, reps * patternSize); 151 } 152 for (int i = 0; i < reps; ++i) { 153 int baseIdx = i * patternSize; 154 uint16_t baseVert = (uint16_t)(i * vertCount); 155 for (int j = 0; j < patternSize; ++j) { 156 data[baseIdx+j] = baseVert + pattern[j]; 157 } 158 } 159 if (useTempData) { 160 if (!buffer->updateData(data, bufferSize)) { 161 SkFAIL("Can't get indices into buffer!"); 162 } 163 SkDELETE_ARRAY(data); 164 } else { 165 buffer->unmap(); 166 } 167 } 168 return buffer; 169} 170 171void GrGpu::clear(const SkIRect* rect, 172 GrColor color, 173 bool canIgnoreRect, 174 GrRenderTarget* renderTarget) { 175 SkASSERT(renderTarget); 176 this->handleDirtyContext(); 177 this->onClear(renderTarget, rect, color, canIgnoreRect); 178} 179 180void GrGpu::clearStencilClip(const SkIRect& rect, 181 bool insideClip, 182 GrRenderTarget* renderTarget) { 183 SkASSERT(renderTarget); 184 this->handleDirtyContext(); 185 this->onClearStencilClip(renderTarget, rect, insideClip); 186} 187 188bool GrGpu::readPixels(GrRenderTarget* target, 189 int left, int top, int width, int height, 190 GrPixelConfig config, void* buffer, 191 size_t rowBytes) { 192 this->handleDirtyContext(); 193 return this->onReadPixels(target, left, top, width, height, 194 config, buffer, rowBytes); 195} 196 197bool GrGpu::writeTexturePixels(GrTexture* texture, 198 int left, int top, int width, int height, 199 GrPixelConfig config, const void* buffer, 200 size_t rowBytes) { 201 this->handleDirtyContext(); 202 return this->onWriteTexturePixels(texture, left, top, width, height, 203 config, buffer, rowBytes); 204} 205 206void GrGpu::resolveRenderTarget(GrRenderTarget* target) { 207 SkASSERT(target); 208 this->handleDirtyContext(); 209 this->onResolveRenderTarget(target); 210} 211 212typedef GrTraceMarkerSet::Iter TMIter; 213void GrGpu::saveActiveTraceMarkers() { 214 if (this->caps()->gpuTracingSupport()) { 215 SkASSERT(0 == fStoredTraceMarkers.count()); 216 fStoredTraceMarkers.addSet(fActiveTraceMarkers); 217 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 218 this->removeGpuTraceMarker(&(*iter)); 219 } 220 } 221} 222 223void GrGpu::restoreActiveTraceMarkers() { 224 if (this->caps()->gpuTracingSupport()) { 225 SkASSERT(0 == fActiveTraceMarkers.count()); 226 for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) { 227 this->addGpuTraceMarker(&(*iter)); 228 } 229 for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) { 230 this->fStoredTraceMarkers.remove(*iter); 231 } 232 } 233} 234 235void GrGpu::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 236 if (this->caps()->gpuTracingSupport()) { 237 SkASSERT(fGpuTraceMarkerCount >= 0); 238 this->fActiveTraceMarkers.add(*marker); 239 this->didAddGpuTraceMarker(); 240 ++fGpuTraceMarkerCount; 241 } 242} 243 244void GrGpu::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 245 if (this->caps()->gpuTracingSupport()) { 246 SkASSERT(fGpuTraceMarkerCount >= 1); 247 this->fActiveTraceMarkers.remove(*marker); 248 this->didRemoveGpuTraceMarker(); 249 --fGpuTraceMarkerCount; 250 } 251} 252 253//////////////////////////////////////////////////////////////////////////////// 254 255static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; 256 257GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535); 258 259static const uint16_t gQuadIndexPattern[] = { 260 0, 1, 2, 0, 2, 3 261}; 262 263const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { 264 if (NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()) { 265 SkSafeUnref(fQuadIndexBuffer); 266 GrGpu* me = const_cast<GrGpu*>(this); 267 fQuadIndexBuffer = me->createInstancedIndexBuffer(gQuadIndexPattern, 268 6, 269 MAX_QUADS, 270 4); 271 } 272 273 return fQuadIndexBuffer; 274} 275 276//////////////////////////////////////////////////////////////////////////////// 277 278void GrGpu::draw(const GrOptDrawState& ds, const GrDrawTarget::DrawInfo& info) { 279 this->handleDirtyContext(); 280 this->onDraw(ds, info); 281} 282 283void GrGpu::stencilPath(const GrOptDrawState& ds, 284 const GrPath* path, 285 const GrStencilSettings& stencilSettings) { 286 this->handleDirtyContext(); 287 this->onStencilPath(ds, path, stencilSettings); 288} 289 290void GrGpu::drawPath(const GrOptDrawState& ds, 291 const GrPath* path, 292 const GrStencilSettings& stencilSettings) { 293 this->handleDirtyContext(); 294 this->onDrawPath(ds, path, stencilSettings); 295} 296 297void GrGpu::drawPaths(const GrOptDrawState& ds, 298 const GrPathRange* pathRange, 299 const void* indices, 300 GrDrawTarget::PathIndexType indexType, 301 const float transformValues[], 302 GrDrawTarget::PathTransformType transformType, 303 int count, 304 const GrStencilSettings& stencilSettings) { 305 this->handleDirtyContext(); 306 pathRange->willDrawPaths(indices, indexType, count); 307 this->onDrawPaths(ds, pathRange, indices, indexType, transformValues, 308 transformType, count, stencilSettings); 309} 310