| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1 | /* | 
| bsalomon@google.com | 1da0746 | 2011-03-10 14:51:57 +0000 | [diff] [blame] | 2 |     Copyright 2011 Google Inc. | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 3 |  | 
 | 4 |     Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |     you may not use this file except in compliance with the License. | 
 | 6 |     You may obtain a copy of the License at | 
 | 7 |  | 
 | 8 |          http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  | 
 | 10 |     Unless required by applicable law or agreed to in writing, software | 
 | 11 |     distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |     See the License for the specific language governing permissions and | 
 | 14 |     limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include "GrContext.h" | 
 | 18 | #include "GrTypes.h" | 
 | 19 | #include "GrTextureCache.h" | 
 | 20 | #include "GrTextStrike.h" | 
 | 21 | #include "GrMemory.h" | 
 | 22 | #include "GrPathIter.h" | 
 | 23 | #include "GrClipIterator.h" | 
 | 24 | #include "GrIndexBuffer.h" | 
 | 25 | #include "GrInOrderDrawBuffer.h" | 
 | 26 | #include "GrBufferAllocPool.h" | 
 | 27 | #include "GrPathRenderer.h" | 
 | 28 |  | 
 | 29 | #define DEFER_TEXT_RENDERING 1 | 
 | 30 |  | 
 | 31 | #define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB) | 
 | 32 |  | 
 | 33 | static const size_t MAX_TEXTURE_CACHE_COUNT = 128; | 
 | 34 | static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024; | 
 | 35 |  | 
 | 36 | static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18; | 
 | 37 | static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4; | 
 | 38 |  | 
 | 39 | // We are currently only batching Text and drawRectToRect, both | 
 | 40 | // of which use the quad index buffer. | 
 | 41 | static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0; | 
 | 42 | static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0; | 
 | 43 |  | 
 | 44 | GrContext* GrContext::Create(GrGpu::Engine engine, | 
 | 45 |                              GrGpu::Platform3DContext context3D) { | 
 | 46 |     GrContext* ctx = NULL; | 
 | 47 |     GrGpu* fGpu = GrGpu::Create(engine, context3D); | 
 | 48 |     if (NULL != fGpu) { | 
 | 49 |         ctx = new GrContext(fGpu); | 
 | 50 |         fGpu->unref(); | 
 | 51 |     } | 
 | 52 |     return ctx; | 
 | 53 | } | 
 | 54 |  | 
 | 55 | GrContext* GrContext::CreateGLShaderContext() { | 
 | 56 |     return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL); | 
 | 57 | } | 
 | 58 |  | 
 | 59 | GrContext::~GrContext() { | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 60 |     this->flush(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 61 |     delete fTextureCache; | 
 | 62 |     delete fFontCache; | 
 | 63 |     delete fDrawBuffer; | 
 | 64 |     delete fDrawBufferVBAllocPool; | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 65 |     delete fDrawBufferIBAllocPool; | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 66 |     GrSafeUnref(fCustomPathRenderer); | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 67 |     GrSafeUnref(fAAFillRectIndexBuffer); | 
 | 68 |     GrSafeUnref(fAAStrokeRectIndexBuffer); | 
 | 69 |     fGpu->unref(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 70 | } | 
 | 71 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 72 | void GrContext::contextLost() { | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 73 |     // abandon first to so destructors | 
 | 74 |     // don't try to free the resources in the API. | 
 | 75 |     fGpu->abandonResources(); | 
 | 76 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 77 |     delete fDrawBuffer; | 
 | 78 |     fDrawBuffer = NULL; | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 79 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 80 |     delete fDrawBufferVBAllocPool; | 
 | 81 |     fDrawBufferVBAllocPool = NULL; | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 82 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 83 |     delete fDrawBufferIBAllocPool; | 
 | 84 |     fDrawBufferIBAllocPool = NULL; | 
 | 85 |  | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 86 |     GrSafeSetNull(fAAFillRectIndexBuffer); | 
 | 87 |     GrSafeSetNull(fAAStrokeRectIndexBuffer); | 
 | 88 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 89 |     fTextureCache->removeAll(); | 
 | 90 |     fFontCache->freeAll(); | 
 | 91 |     fGpu->markContextDirty(); | 
 | 92 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 93 |     this->setupDrawBuffer(); | 
 | 94 | } | 
 | 95 |  | 
 | 96 | void GrContext::resetContext() { | 
 | 97 |     fGpu->markContextDirty(); | 
 | 98 | } | 
 | 99 |  | 
 | 100 | void GrContext::freeGpuResources() { | 
 | 101 |     this->flush(); | 
 | 102 |     fTextureCache->removeAll(); | 
 | 103 |     fFontCache->freeAll(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 104 | } | 
 | 105 |  | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 106 | //////////////////////////////////////////////////////////////////////////////// | 
 | 107 |  | 
 | 108 |  | 
 | 109 | enum { | 
 | 110 |     kNPOTBit    = 0x1, | 
 | 111 |     kFilterBit  = 0x2, | 
 | 112 |     kKeylessBit = 0x4, | 
 | 113 | }; | 
 | 114 |  | 
 | 115 | bool GrContext::finalizeTextureKey(GrTextureKey* key, | 
 | 116 |                                    const GrSamplerState& sampler, | 
 | 117 |                                    bool keyless) const { | 
 | 118 |     uint32_t bits = 0; | 
 | 119 |     uint16_t width = key->width(); | 
 | 120 |     uint16_t height = key->height(); | 
 | 121 |  | 
 | 122 |     if (!fGpu->npotTextureTileSupport()) { | 
 | 123 |         bool isPow2 = GrIsPow2(width) && GrIsPow2(height); | 
 | 124 |  | 
 | 125 |         bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) || | 
 | 126 |                      (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode); | 
 | 127 |  | 
 | 128 |         if (tiled && !isPow2) { | 
 | 129 |             bits |= kNPOTBit; | 
 | 130 |             if (sampler.isFilter()) { | 
 | 131 |                 bits |= kFilterBit; | 
 | 132 |             } | 
 | 133 |         } | 
 | 134 |     } | 
 | 135 |  | 
 | 136 |     if (keyless) { | 
 | 137 |         bits |= kKeylessBit; | 
 | 138 |     } | 
 | 139 |     key->finalize(bits); | 
 | 140 |     return 0 != bits; | 
 | 141 | } | 
 | 142 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 143 | GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key, | 
 | 144 |                                               const GrSamplerState& sampler) { | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 145 |     finalizeTextureKey(key, sampler, false); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 146 |     return fTextureCache->findAndLock(*key); | 
 | 147 | } | 
 | 148 |  | 
 | 149 | static void stretchImage(void* dst, | 
 | 150 |                          int dstW, | 
 | 151 |                          int dstH, | 
 | 152 |                          void* src, | 
 | 153 |                          int srcW, | 
 | 154 |                          int srcH, | 
 | 155 |                          int bpp) { | 
 | 156 |     GrFixed dx = (srcW << 16) / dstW; | 
 | 157 |     GrFixed dy = (srcH << 16) / dstH; | 
 | 158 |  | 
 | 159 |     GrFixed y = dy >> 1; | 
 | 160 |  | 
 | 161 |     int dstXLimit = dstW*bpp; | 
 | 162 |     for (int j = 0; j < dstH; ++j) { | 
 | 163 |         GrFixed x = dx >> 1; | 
 | 164 |         void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp; | 
 | 165 |         void* dstRow = (uint8_t*)dst + j*dstW*bpp; | 
 | 166 |         for (int i = 0; i < dstXLimit; i += bpp) { | 
 | 167 |             memcpy((uint8_t*) dstRow + i, | 
 | 168 |                    (uint8_t*) srcRow + (x>>16)*bpp, | 
 | 169 |                    bpp); | 
 | 170 |             x += dx; | 
 | 171 |         } | 
 | 172 |         y += dy; | 
 | 173 |     } | 
 | 174 | } | 
 | 175 |  | 
 | 176 | GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key, | 
 | 177 |                                                 const GrSamplerState& sampler, | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 178 |                                                 const GrTextureDesc& desc, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 179 |                                                 void* srcData, size_t rowBytes) { | 
 | 180 |     GrAssert(key->width() == desc.fWidth); | 
 | 181 |     GrAssert(key->height() == desc.fHeight); | 
 | 182 |  | 
 | 183 | #if GR_DUMP_TEXTURE_UPLOAD | 
 | 184 |     GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight); | 
 | 185 | #endif | 
 | 186 |  | 
 | 187 |     GrTextureEntry* entry = NULL; | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 188 |     bool special = finalizeTextureKey(key, sampler, false); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 189 |     if (special) { | 
 | 190 |         GrTextureEntry* clampEntry; | 
 | 191 |         GrTextureKey clampKey(*key); | 
 | 192 |         clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter()); | 
 | 193 |  | 
 | 194 |         if (NULL == clampEntry) { | 
 | 195 |             clampEntry = createAndLockTexture(&clampKey, | 
 | 196 |                                               GrSamplerState::ClampNoFilter(), | 
 | 197 |                                               desc, srcData, rowBytes); | 
 | 198 |             GrAssert(NULL != clampEntry); | 
 | 199 |             if (NULL == clampEntry) { | 
 | 200 |                 return NULL; | 
 | 201 |             } | 
 | 202 |         } | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 203 |         GrTextureDesc rtDesc = desc; | 
 | 204 |         rtDesc.fFlags =  rtDesc.fFlags | | 
 | 205 |                          kRenderTarget_GrTextureFlagBit | | 
 | 206 |                          kNoStencil_GrTextureFlagBit; | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 207 |         rtDesc.fWidth  = GrNextPow2(GrMax<int>(desc.fWidth, | 
 | 208 |                                                fGpu->minRenderTargetWidth())); | 
 | 209 |         rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight, | 
 | 210 |                                                fGpu->minRenderTargetHeight())); | 
 | 211 |  | 
 | 212 |         GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0); | 
 | 213 |  | 
 | 214 |         if (NULL != texture) { | 
 | 215 |             GrDrawTarget::AutoStateRestore asr(fGpu); | 
 | 216 |             fGpu->setRenderTarget(texture->asRenderTarget()); | 
 | 217 |             fGpu->setTexture(0, clampEntry->texture()); | 
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 218 |             fGpu->disableStencil(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 219 |             fGpu->setViewMatrix(GrMatrix::I()); | 
 | 220 |             fGpu->setAlpha(0xff); | 
 | 221 |             fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); | 
 | 222 |             fGpu->disableState(GrDrawTarget::kDither_StateBit | | 
 | 223 |                                GrDrawTarget::kClip_StateBit   | | 
 | 224 |                                GrDrawTarget::kAntialias_StateBit); | 
 | 225 |             GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode, | 
 | 226 |                                           GrSamplerState::kClamp_WrapMode, | 
 | 227 |                                           sampler.isFilter()); | 
 | 228 |             fGpu->setSamplerState(0, stretchSampler); | 
 | 229 |  | 
 | 230 |             static const GrVertexLayout layout = | 
 | 231 |                                 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0); | 
 | 232 |             GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0); | 
 | 233 |  | 
 | 234 |             if (arg.succeeded()) { | 
 | 235 |                 GrPoint* verts = (GrPoint*) arg.vertices(); | 
 | 236 |                 verts[0].setIRectFan(0, 0, | 
 | 237 |                                      texture->width(), | 
 | 238 |                                      texture->height(), | 
 | 239 |                                      2*sizeof(GrPoint)); | 
 | 240 |                 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint)); | 
 | 241 |                 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, | 
 | 242 |                                      0, 4); | 
 | 243 |                 entry = fTextureCache->createAndLock(*key, texture); | 
 | 244 |             } | 
| bsalomon@google.com | 1da0746 | 2011-03-10 14:51:57 +0000 | [diff] [blame] | 245 |             texture->releaseRenderTarget(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 246 |         } else { | 
 | 247 |             // TODO: Our CPU stretch doesn't filter. But we create separate | 
 | 248 |             // stretched textures when the sampler state is either filtered or | 
 | 249 |             // not. Either implement filtered stretch blit on CPU or just create | 
 | 250 |             // one when FBO case fails. | 
 | 251 |  | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 252 |             rtDesc.fFlags = kNone_GrTextureFlags; | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 253 |             // no longer need to clamp at min RT size. | 
 | 254 |             rtDesc.fWidth  = GrNextPow2(desc.fWidth); | 
 | 255 |             rtDesc.fHeight = GrNextPow2(desc.fHeight); | 
| bsalomon@google.com | 669fdc4 | 2011-04-05 17:08:27 +0000 | [diff] [blame] | 256 |             int bpp = GrBytesPerPixel(desc.fFormat); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 257 |             GrAutoSMalloc<128*128*4> stretchedPixels(bpp * | 
 | 258 |                                                      rtDesc.fWidth * | 
 | 259 |                                                      rtDesc.fHeight); | 
 | 260 |             stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight, | 
 | 261 |                          srcData, desc.fWidth, desc.fHeight, bpp); | 
 | 262 |  | 
 | 263 |             size_t stretchedRowBytes = rtDesc.fWidth * bpp; | 
 | 264 |  | 
 | 265 |             GrTexture* texture = fGpu->createTexture(rtDesc, | 
 | 266 |                                                      stretchedPixels.get(), | 
 | 267 |                                                      stretchedRowBytes); | 
 | 268 |             GrAssert(NULL != texture); | 
 | 269 |             entry = fTextureCache->createAndLock(*key, texture); | 
 | 270 |         } | 
 | 271 |         fTextureCache->unlock(clampEntry); | 
 | 272 |  | 
 | 273 |     } else { | 
 | 274 |         GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes); | 
 | 275 |         if (NULL != texture) { | 
 | 276 |             entry = fTextureCache->createAndLock(*key, texture); | 
 | 277 |         } else { | 
 | 278 |             entry = NULL; | 
 | 279 |         } | 
 | 280 |     } | 
 | 281 |     return entry; | 
 | 282 | } | 
 | 283 |  | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 284 | GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc, | 
 | 285 |                                               const GrSamplerState& state) { | 
 | 286 |     uint32_t p0 = desc.fFormat; | 
 | 287 |     uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags; | 
 | 288 |     GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight); | 
 | 289 |     this->finalizeTextureKey(&key, state, true); | 
 | 290 |     GrTextureEntry* entry = fTextureCache->findAndLock(key); | 
 | 291 |     if (NULL == entry) { | 
 | 292 |         GrTexture* texture = fGpu->createTexture(desc, NULL, 0); | 
 | 293 |         if (NULL != texture) { | 
 | 294 |             entry = fTextureCache->createAndLock(key, texture); | 
 | 295 |         } | 
 | 296 |     } | 
 | 297 |     // If the caller gives us the same desc/sampler twice we don't want | 
 | 298 |     // to return the same texture the second time (unless it was previously | 
 | 299 |     // released). So we detach the entry from the cache and reattach at release. | 
 | 300 |     if (NULL != entry) { | 
 | 301 |         fTextureCache->detach(entry); | 
 | 302 |     } | 
 | 303 |     return entry; | 
 | 304 | } | 
 | 305 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 306 | void GrContext::unlockTexture(GrTextureEntry* entry) { | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 307 |     if (kKeylessBit & entry->key().getPrivateBits()) { | 
 | 308 |         fTextureCache->reattachAndUnlock(entry); | 
 | 309 |     } else { | 
 | 310 |         fTextureCache->unlock(entry); | 
 | 311 |     } | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 312 | } | 
 | 313 |  | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 314 | GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 315 |                                             void* srcData, | 
 | 316 |                                             size_t rowBytes) { | 
 | 317 |     return fGpu->createTexture(desc, srcData, rowBytes); | 
 | 318 | } | 
 | 319 |  | 
 | 320 | void GrContext::getTextureCacheLimits(int* maxTextures, | 
 | 321 |                                       size_t* maxTextureBytes) const { | 
 | 322 |     fTextureCache->getLimits(maxTextures, maxTextureBytes); | 
 | 323 | } | 
 | 324 |  | 
 | 325 | void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) { | 
 | 326 |     fTextureCache->setLimits(maxTextures, maxTextureBytes); | 
 | 327 | } | 
 | 328 |  | 
 | 329 | int GrContext::getMaxTextureDimension() { | 
 | 330 |     return fGpu->maxTextureDimension(); | 
 | 331 | } | 
 | 332 |  | 
 | 333 | /////////////////////////////////////////////////////////////////////////////// | 
 | 334 |  | 
| bsalomon@google.com | 5877ffd | 2011-04-11 17:58:48 +0000 | [diff] [blame] | 335 | GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) { | 
 | 336 |     // validate flags here so that GrGpu subclasses don't have to check | 
 | 337 |     if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType && | 
 | 338 |         0 != desc.fRenderTargetFlags) { | 
 | 339 |             return NULL; | 
 | 340 |     } | 
 | 341 |     if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) && | 
 | 342 |         (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) { | 
 | 343 |             return NULL; | 
 | 344 |     } | 
 | 345 |     if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType && | 
 | 346 |         (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) && | 
 | 347 |         !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) { | 
 | 348 |         return NULL; | 
 | 349 |     } | 
 | 350 |     return fGpu->createPlatformSurface(desc); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 351 | } | 
 | 352 |  | 
| bsalomon@google.com | 5877ffd | 2011-04-11 17:58:48 +0000 | [diff] [blame] | 353 | /////////////////////////////////////////////////////////////////////////////// | 
 | 354 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 355 | bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler, | 
 | 356 |                                           int width, int height) { | 
 | 357 |     if (!fGpu->supports8BitPalette()) { | 
 | 358 |         return false; | 
 | 359 |     } | 
 | 360 |  | 
 | 361 |  | 
 | 362 |     bool isPow2 = GrIsPow2(width) && GrIsPow2(height); | 
 | 363 |  | 
 | 364 |     if (!isPow2) { | 
 | 365 |         if (!fGpu->npotTextureSupport()) { | 
 | 366 |             return false; | 
 | 367 |         } | 
 | 368 |  | 
 | 369 |         bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode || | 
 | 370 |                      sampler.getWrapY() != GrSamplerState::kClamp_WrapMode; | 
 | 371 |         if (tiled && !fGpu->npotTextureTileSupport()) { | 
 | 372 |             return false; | 
 | 373 |         } | 
 | 374 |     } | 
 | 375 |     return true; | 
 | 376 | } | 
 | 377 |  | 
 | 378 | //////////////////////////////////////////////////////////////////////////////// | 
 | 379 |  | 
 | 380 | void GrContext::setClip(const GrClip& clip) { | 
 | 381 |     fGpu->setClip(clip); | 
 | 382 |     fGpu->enableState(GrDrawTarget::kClip_StateBit); | 
 | 383 | } | 
 | 384 |  | 
 | 385 | void GrContext::setClip(const GrIRect& rect) { | 
 | 386 |     GrClip clip; | 
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 387 |     clip.setFromIRect(rect); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 388 |     fGpu->setClip(clip); | 
 | 389 | } | 
 | 390 |  | 
 | 391 | //////////////////////////////////////////////////////////////////////////////// | 
 | 392 |  | 
| bsalomon@google.com | 398109c | 2011-04-14 18:40:27 +0000 | [diff] [blame] | 393 | void GrContext::clear(GrColor color) { | 
 | 394 |     // gpu flush call is immediate, must flush.  | 
 | 395 |     // (could in theory skip draws to current render target.) | 
 | 396 |     this->flush(); | 
 | 397 |     fGpu->clear(color); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 398 | } | 
 | 399 |  | 
 | 400 | void GrContext::drawPaint(const GrPaint& paint) { | 
 | 401 |     // set rect to be big enough to fill the space, but not super-huge, so we | 
 | 402 |     // don't overflow fixed-point implementations | 
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 403 |     GrRect r; | 
 | 404 |     r.setLTRB(0, 0, | 
 | 405 |               GrIntToScalar(getRenderTarget()->width()), | 
 | 406 |               GrIntToScalar(getRenderTarget()->height())); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 407 |     GrMatrix inverse; | 
 | 408 |     if (fGpu->getViewInverse(&inverse)) { | 
 | 409 |         inverse.mapRect(&r); | 
 | 410 |     } else { | 
 | 411 |         GrPrintf("---- fGpu->getViewInverse failed\n"); | 
 | 412 |     } | 
 | 413 |     this->drawRect(paint, r); | 
 | 414 | } | 
 | 415 |  | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 416 | //////////////////////////////////////////////////////////////////////////////// | 
 | 417 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 418 | /*  create a triangle strip that strokes the specified triangle. There are 8 | 
 | 419 |  unique vertices, but we repreat the last 2 to close up. Alternatively we | 
 | 420 |  could use an indices array, and then only send 8 verts, but not sure that | 
 | 421 |  would be faster. | 
 | 422 |  */ | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 423 | static void setStrokeRectStrip(GrPoint verts[10], GrRect rect, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 424 |                                GrScalar width) { | 
 | 425 |     const GrScalar rad = GrScalarHalf(width); | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 426 |     rect.sort(); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 427 |  | 
 | 428 |     verts[0].set(rect.fLeft + rad, rect.fTop + rad); | 
 | 429 |     verts[1].set(rect.fLeft - rad, rect.fTop - rad); | 
 | 430 |     verts[2].set(rect.fRight - rad, rect.fTop + rad); | 
 | 431 |     verts[3].set(rect.fRight + rad, rect.fTop - rad); | 
 | 432 |     verts[4].set(rect.fRight - rad, rect.fBottom - rad); | 
 | 433 |     verts[5].set(rect.fRight + rad, rect.fBottom + rad); | 
 | 434 |     verts[6].set(rect.fLeft + rad, rect.fBottom - rad); | 
 | 435 |     verts[7].set(rect.fLeft - rad, rect.fBottom + rad); | 
 | 436 |     verts[8] = verts[0]; | 
 | 437 |     verts[9] = verts[1]; | 
 | 438 | } | 
 | 439 |  | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 440 | static GrColor getColorForMesh(const GrPaint& paint) { | 
 | 441 |     if (NULL == paint.getTexture()) { | 
 | 442 |         return paint.fColor; | 
 | 443 |     } else { | 
 | 444 |         unsigned a = GrColorUnpackA(paint.fColor); | 
 | 445 |         return GrColorPackRGBA(a, a, a, a); | 
 | 446 |     } | 
 | 447 | } | 
 | 448 |  | 
 | 449 | static void setInsetFan(GrPoint* pts, size_t stride, | 
 | 450 |                         const GrRect& r, GrScalar dx, GrScalar dy) { | 
 | 451 |     pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride); | 
 | 452 | } | 
 | 453 |  | 
 | 454 | static const uint16_t gFillAARectIdx[] = { | 
 | 455 |     0, 1, 5, 5, 4, 0, | 
 | 456 |     1, 2, 6, 6, 5, 1, | 
 | 457 |     2, 3, 7, 7, 6, 2, | 
 | 458 |     3, 0, 4, 4, 7, 3, | 
 | 459 |     4, 5, 6, 6, 7, 4, | 
 | 460 | }; | 
 | 461 |  | 
 | 462 | int GrContext::aaFillRectIndexCount() const { | 
 | 463 |     return GR_ARRAY_COUNT(gFillAARectIdx); | 
 | 464 | } | 
 | 465 |  | 
 | 466 | GrIndexBuffer* GrContext::aaFillRectIndexBuffer() { | 
 | 467 |     if (NULL == fAAFillRectIndexBuffer) { | 
 | 468 |         fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx), | 
 | 469 |                                                          false); | 
 | 470 |         GrAssert(NULL != fAAFillRectIndexBuffer); | 
 | 471 | #if GR_DEBUG | 
 | 472 |         bool updated = | 
 | 473 | #endif | 
 | 474 |         fAAFillRectIndexBuffer->updateData(gFillAARectIdx, | 
 | 475 |                                            sizeof(gFillAARectIdx)); | 
 | 476 |         GR_DEBUGASSERT(updated); | 
 | 477 |     } | 
 | 478 |     return fAAFillRectIndexBuffer; | 
 | 479 | } | 
 | 480 |  | 
 | 481 | static const uint16_t gStrokeAARectIdx[] = { | 
 | 482 |     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, | 
 | 483 |     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, | 
 | 484 |     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, | 
 | 485 |     3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, | 
 | 486 |  | 
 | 487 |     0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, | 
 | 488 |     1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, | 
 | 489 |     2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, | 
 | 490 |     3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, | 
 | 491 |  | 
 | 492 |     0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, | 
 | 493 |     1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, | 
 | 494 |     2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, | 
 | 495 |     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, | 
 | 496 | }; | 
 | 497 |  | 
 | 498 | int GrContext::aaStrokeRectIndexCount() const { | 
 | 499 |     return GR_ARRAY_COUNT(gStrokeAARectIdx); | 
 | 500 | } | 
 | 501 |  | 
 | 502 | GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() { | 
 | 503 |     if (NULL == fAAStrokeRectIndexBuffer) { | 
 | 504 |         fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx), | 
 | 505 |                                                            false); | 
 | 506 |         GrAssert(NULL != fAAStrokeRectIndexBuffer); | 
 | 507 | #if GR_DEBUG | 
 | 508 |         bool updated = | 
 | 509 | #endif | 
 | 510 |         fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx, | 
 | 511 |                                              sizeof(gStrokeAARectIdx)); | 
 | 512 |         GR_DEBUGASSERT(updated); | 
 | 513 |     } | 
 | 514 |     return fAAStrokeRectIndexBuffer; | 
 | 515 | } | 
 | 516 |  | 
 | 517 | void GrContext::fillAARect(GrDrawTarget* target, | 
 | 518 |                            const GrPaint& paint, | 
 | 519 |                            const GrRect& devRect) { | 
 | 520 |  | 
 | 521 |     GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit; | 
 | 522 |     if (NULL != paint.getTexture()) { | 
 | 523 |         layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); | 
 | 524 |     } | 
 | 525 |  | 
 | 526 |     size_t vsize = GrDrawTarget::VertexSize(layout); | 
 | 527 |  | 
 | 528 |     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0); | 
 | 529 |  | 
 | 530 |     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); | 
 | 531 |  | 
 | 532 |     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); | 
 | 533 |     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); | 
 | 534 |  | 
 | 535 |     setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf); | 
 | 536 |     setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf); | 
 | 537 |  | 
 | 538 |     verts += sizeof(GrPoint); | 
 | 539 |     for (int i = 0; i < 4; ++i) { | 
 | 540 |         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; | 
 | 541 |     } | 
 | 542 |  | 
 | 543 |     GrColor innerColor = getColorForMesh(paint); | 
 | 544 |     verts += 4 * vsize; | 
 | 545 |     for (int i = 0; i < 4; ++i) { | 
 | 546 |         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; | 
 | 547 |     } | 
 | 548 |  | 
 | 549 |     target->setIndexSourceToBuffer(this->aaFillRectIndexBuffer()); | 
 | 550 |  | 
 | 551 |     target->drawIndexed(kTriangles_PrimitiveType, 0, | 
 | 552 |                          0, 8, this->aaFillRectIndexCount()); | 
 | 553 | } | 
 | 554 |  | 
 | 555 | void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint, | 
 | 556 |                              const GrRect& devRect, const GrVec& devStrokeSize) { | 
 | 557 |     const GrScalar& dx = devStrokeSize.fX; | 
 | 558 |     const GrScalar& dy = devStrokeSize.fY; | 
 | 559 |     const GrScalar rx = GrMul(dx, GR_ScalarHalf); | 
 | 560 |     const GrScalar ry = GrMul(dy, GR_ScalarHalf); | 
 | 561 |  | 
 | 562 |     GrVertexLayout layout = GrDrawTarget::kColor_VertexLayoutBit; | 
 | 563 |  | 
 | 564 |     if (NULL != paint.getTexture()) { | 
 | 565 |         layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); | 
 | 566 |     } | 
 | 567 |  | 
 | 568 |     GrScalar spare; | 
 | 569 |     { | 
 | 570 |         GrScalar w = devRect.width() - dx; | 
 | 571 |         GrScalar h = devRect.height() - dy; | 
 | 572 |         spare = GrMin(w, h); | 
 | 573 |     } | 
 | 574 |  | 
 | 575 |     if (spare <= 0) { | 
 | 576 |         GrRect r(devRect); | 
 | 577 |         r.inset(-rx, -ry); | 
 | 578 |         fillAARect(target, paint, r); | 
 | 579 |         return; | 
 | 580 |     } | 
 | 581 |  | 
 | 582 |     size_t vsize = GrDrawTarget::VertexSize(layout); | 
 | 583 |  | 
 | 584 |     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0); | 
 | 585 |  | 
 | 586 |     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); | 
 | 587 |  | 
 | 588 |     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); | 
 | 589 |     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); | 
 | 590 |     GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize); | 
 | 591 |     GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize); | 
 | 592 |  | 
 | 593 |     setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf); | 
 | 594 |     setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf); | 
 | 595 |     setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf); | 
 | 596 |     setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf); | 
 | 597 |  | 
 | 598 |     verts += sizeof(GrPoint); | 
 | 599 |     for (int i = 0; i < 4; ++i) { | 
 | 600 |         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; | 
 | 601 |     } | 
 | 602 |  | 
 | 603 |     GrColor innerColor = getColorForMesh(paint); | 
 | 604 |     verts += 4 * vsize; | 
 | 605 |     for (int i = 0; i < 8; ++i) { | 
 | 606 |         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; | 
 | 607 |     } | 
 | 608 |  | 
 | 609 |     verts += 8 * vsize; | 
 | 610 |     for (int i = 0; i < 8; ++i) { | 
 | 611 |         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; | 
 | 612 |     } | 
 | 613 |  | 
 | 614 |     target->setIndexSourceToBuffer(aaStrokeRectIndexBuffer()); | 
 | 615 |     target->drawIndexed(kTriangles_PrimitiveType, | 
 | 616 |                         0, 0, 16, aaStrokeRectIndexCount()); | 
 | 617 | } | 
 | 618 |  | 
 | 619 | static bool apply_aa_to_rect(GrDrawTarget* target, | 
 | 620 |                              GrGpu* gpu, | 
 | 621 |                              const GrPaint& paint, | 
 | 622 |                              const GrRect& rect, | 
 | 623 |                              GrScalar width,  | 
 | 624 |                              const GrMatrix* matrix, | 
 | 625 |                              GrMatrix* combinedMatrix, | 
 | 626 |                              GrRect* devRect) { | 
 | 627 |     // we use a simple alpha ramp to do aa on axis-aligned rects | 
 | 628 |     // do AA with alpha ramp if the caller requested AA, the rect  | 
 | 629 |     // will be axis-aligned,the render target is not | 
 | 630 |     // multisampled, and the rect won't land on integer coords. | 
 | 631 |  | 
 | 632 |     if (!paint.fAntiAlias) { | 
 | 633 |         return false; | 
 | 634 |     } | 
 | 635 |  | 
 | 636 |     if (target->getRenderTarget()->isMultisampled()) { | 
 | 637 |         return false; | 
 | 638 |     } | 
 | 639 |  | 
 | 640 |     if (0 == width && gpu->supportsAALines()) { | 
 | 641 |         return false; | 
 | 642 |     } | 
 | 643 |  | 
 | 644 |     if (!target->getViewMatrix().preservesAxisAlignment()) { | 
 | 645 |         return false; | 
 | 646 |     } | 
 | 647 |  | 
 | 648 |     if (NULL != matrix &&  | 
 | 649 |         !matrix->preservesAxisAlignment()) { | 
 | 650 |         return false; | 
 | 651 |     } | 
 | 652 |  | 
 | 653 |     *combinedMatrix = target->getViewMatrix(); | 
 | 654 |     if (NULL != matrix) { | 
 | 655 |         combinedMatrix->preConcat(*matrix); | 
 | 656 |         GrAssert(combinedMatrix->preservesAxisAlignment()); | 
 | 657 |     } | 
 | 658 |      | 
 | 659 |     combinedMatrix->mapRect(devRect, rect); | 
 | 660 |     devRect->sort(); | 
 | 661 |  | 
 | 662 |     if (width < 0) { | 
 | 663 |         return !devRect->isIRect(); | 
 | 664 |     } else { | 
 | 665 |         return true; | 
 | 666 |     } | 
 | 667 | } | 
 | 668 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 669 | void GrContext::drawRect(const GrPaint& paint, | 
 | 670 |                          const GrRect& rect, | 
 | 671 |                          GrScalar width, | 
 | 672 |                          const GrMatrix* matrix) { | 
 | 673 |  | 
 | 674 |     bool textured = NULL != paint.getTexture(); | 
 | 675 |  | 
 | 676 |     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 677 |  | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 678 |     GrRect devRect = rect; | 
 | 679 |     GrMatrix combinedMatrix; | 
 | 680 |     bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix,  | 
 | 681 |                                  &combinedMatrix, &devRect); | 
 | 682 |  | 
 | 683 |     if (doAA) { | 
 | 684 |         GrDrawTarget::AutoViewMatrixRestore avm(target); | 
 | 685 |         if (textured) { | 
 | 686 |             GrMatrix inv; | 
 | 687 |             if (combinedMatrix.invert(&inv)) { | 
 | 688 |                 target->preConcatSamplerMatrix(0, inv); | 
 | 689 |             } | 
 | 690 |         } | 
 | 691 |         target->setViewMatrix(GrMatrix::I()); | 
 | 692 |         if (width >= 0) { | 
 | 693 |             GrVec strokeSize;; | 
 | 694 |             if (width > 0) { | 
 | 695 |                 strokeSize.set(width, width); | 
 | 696 |                 combinedMatrix.mapVec(&strokeSize); | 
 | 697 |                 strokeSize.setAbs(strokeSize); | 
 | 698 |             } else { | 
 | 699 |                 strokeSize.set(GR_Scalar1, GR_Scalar1); | 
 | 700 |             } | 
 | 701 |             strokeAARect(target, paint, devRect, strokeSize); | 
 | 702 |         } else { | 
 | 703 |             fillAARect(target, paint, devRect); | 
 | 704 |         } | 
 | 705 |         return; | 
 | 706 |     } | 
 | 707 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 708 |     if (width >= 0) { | 
 | 709 |         // TODO: consider making static vertex buffers for these cases. | 
 | 710 |         // Hairline could be done by just adding closing vertex to | 
 | 711 |         // unitSquareVertexBuffer() | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 712 |         GrVertexLayout layout = textured ? | 
 | 713 |                             GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) : | 
 | 714 |                             0; | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 715 |         static const int worstCaseVertCount = 10; | 
 | 716 |         GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0); | 
 | 717 |  | 
 | 718 |         if (!geo.succeeded()) { | 
 | 719 |             return; | 
 | 720 |         } | 
 | 721 |  | 
 | 722 |         GrPrimitiveType primType; | 
 | 723 |         int vertCount; | 
 | 724 |         GrPoint* vertex = geo.positions(); | 
 | 725 |  | 
 | 726 |         if (width > 0) { | 
 | 727 |             vertCount = 10; | 
 | 728 |             primType = kTriangleStrip_PrimitiveType; | 
 | 729 |             setStrokeRectStrip(vertex, rect, width); | 
 | 730 |         } else { | 
 | 731 |             // hairline | 
 | 732 |             vertCount = 5; | 
 | 733 |             primType = kLineStrip_PrimitiveType; | 
 | 734 |             vertex[0].set(rect.fLeft, rect.fTop); | 
 | 735 |             vertex[1].set(rect.fRight, rect.fTop); | 
 | 736 |             vertex[2].set(rect.fRight, rect.fBottom); | 
 | 737 |             vertex[3].set(rect.fLeft, rect.fBottom); | 
 | 738 |             vertex[4].set(rect.fLeft, rect.fTop); | 
 | 739 |         } | 
 | 740 |  | 
 | 741 |         GrDrawTarget::AutoViewMatrixRestore avmr; | 
 | 742 |         if (NULL != matrix) { | 
 | 743 |             avmr.set(target); | 
 | 744 |             target->preConcatViewMatrix(*matrix); | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 745 |             if (textured) { | 
 | 746 |                 target->preConcatSamplerMatrix(0, *matrix); | 
 | 747 |             } | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 748 |         } | 
 | 749 |  | 
 | 750 |         target->drawNonIndexed(primType, 0, vertCount); | 
 | 751 |     } else { | 
 | 752 |         #if GR_STATIC_RECT_VB | 
 | 753 |             GrVertexLayout layout = (textured) ? | 
 | 754 |                             GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) : | 
 | 755 |                             0; | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 756 |             target->setVertexSourceToBuffer(layout, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 757 |                                             fGpu->getUnitSquareVertexBuffer()); | 
 | 758 |             GrDrawTarget::AutoViewMatrixRestore avmr(target); | 
 | 759 |             GrMatrix m; | 
 | 760 |             m.setAll(rect.width(), 0,             rect.fLeft, | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 761 |                         0,            rect.height(), rect.fTop, | 
 | 762 |                         0,            0,             GrMatrix::I()[8]); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 763 |  | 
 | 764 |             if (NULL != matrix) { | 
 | 765 |                 m.postConcat(*matrix); | 
 | 766 |             } | 
 | 767 |  | 
 | 768 |             target->preConcatViewMatrix(m); | 
 | 769 |  | 
 | 770 |             if (textured) { | 
 | 771 |                 target->preConcatSamplerMatrix(0, m); | 
 | 772 |             } | 
 | 773 |             target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); | 
 | 774 |         #else | 
 | 775 |             target->drawSimpleRect(rect, matrix, textured ? 1 : 0); | 
 | 776 |         #endif | 
 | 777 |     } | 
 | 778 | } | 
 | 779 |  | 
 | 780 | void GrContext::drawRectToRect(const GrPaint& paint, | 
 | 781 |                                const GrRect& dstRect, | 
 | 782 |                                const GrRect& srcRect, | 
 | 783 |                                const GrMatrix* dstMatrix, | 
 | 784 |                                const GrMatrix* srcMatrix) { | 
 | 785 |  | 
 | 786 |     if (NULL == paint.getTexture()) { | 
 | 787 |         drawRect(paint, dstRect, -1, dstMatrix); | 
 | 788 |         return; | 
 | 789 |     } | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 790 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 791 |     GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB); | 
 | 792 |  | 
 | 793 | #if GR_STATIC_RECT_VB | 
 | 794 |     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 795 |  | 
 | 796 |     GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); | 
 | 797 |     GrDrawTarget::AutoViewMatrixRestore avmr(target); | 
 | 798 |  | 
 | 799 |     GrMatrix m; | 
 | 800 |  | 
 | 801 |     m.setAll(dstRect.width(), 0,                dstRect.fLeft, | 
 | 802 |              0,               dstRect.height(), dstRect.fTop, | 
 | 803 |              0,               0,                GrMatrix::I()[8]); | 
 | 804 |     if (NULL != dstMatrix) { | 
 | 805 |         m.postConcat(*dstMatrix); | 
 | 806 |     } | 
 | 807 |     target->preConcatViewMatrix(m); | 
 | 808 |  | 
 | 809 |     m.setAll(srcRect.width(), 0,                srcRect.fLeft, | 
 | 810 |              0,               srcRect.height(), srcRect.fTop, | 
 | 811 |              0,               0,                GrMatrix::I()[8]); | 
 | 812 |     if (NULL != srcMatrix) { | 
 | 813 |         m.postConcat(*srcMatrix); | 
 | 814 |     } | 
 | 815 |     target->preConcatSamplerMatrix(0, m); | 
 | 816 |  | 
 | 817 |     target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer()); | 
 | 818 |     target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); | 
 | 819 | #else | 
 | 820 |  | 
 | 821 |     GrDrawTarget* target; | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 822 | #if BATCH_RECT_TO_RECT | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 823 |     target = this->prepareToDraw(paint, kBuffered_DrawCategory); | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 824 | #else | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 825 |     target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 826 | #endif | 
 | 827 |  | 
 | 828 |     const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL}; | 
 | 829 |     const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL}; | 
 | 830 |     srcRects[0] = &srcRect; | 
 | 831 |     srcMatrices[0] = srcMatrix; | 
 | 832 |  | 
 | 833 |     target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices); | 
 | 834 | #endif | 
 | 835 | } | 
 | 836 |  | 
 | 837 | void GrContext::drawVertices(const GrPaint& paint, | 
 | 838 |                              GrPrimitiveType primitiveType, | 
 | 839 |                              int vertexCount, | 
 | 840 |                              const GrPoint positions[], | 
 | 841 |                              const GrPoint texCoords[], | 
 | 842 |                              const GrColor colors[], | 
 | 843 |                              const uint16_t indices[], | 
 | 844 |                              int indexCount) { | 
 | 845 |     GrVertexLayout layout = 0; | 
 | 846 |     int vertexSize = sizeof(GrPoint); | 
 | 847 |  | 
 | 848 |     GrDrawTarget::AutoReleaseGeometry geo; | 
 | 849 |  | 
 | 850 |     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 851 |  | 
 | 852 |     if (NULL != paint.getTexture()) { | 
 | 853 |         if (NULL == texCoords) { | 
 | 854 |             layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); | 
 | 855 |         } else { | 
 | 856 |             layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0); | 
 | 857 |             vertexSize += sizeof(GrPoint); | 
 | 858 |         } | 
 | 859 |     } | 
 | 860 |  | 
 | 861 |     if (NULL != colors) { | 
 | 862 |         layout |= GrDrawTarget::kColor_VertexLayoutBit; | 
 | 863 |         vertexSize += sizeof(GrColor); | 
 | 864 |     } | 
 | 865 |  | 
 | 866 |     if (sizeof(GrPoint) != vertexSize) { | 
 | 867 |         if (!geo.set(target, layout, vertexCount, 0)) { | 
 | 868 |             GrPrintf("Failed to get space for vertices!"); | 
 | 869 |             return; | 
 | 870 |         } | 
 | 871 |         int texOffsets[GrDrawTarget::kMaxTexCoords]; | 
 | 872 |         int colorOffset; | 
 | 873 |         int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout, | 
 | 874 |                                                             texOffsets, | 
 | 875 |                                                             &colorOffset); | 
 | 876 |         void* curVertex = geo.vertices(); | 
 | 877 |  | 
 | 878 |         for (int i = 0; i < vertexCount; ++i) { | 
 | 879 |             *((GrPoint*)curVertex) = positions[i]; | 
 | 880 |  | 
 | 881 |             if (texOffsets[0] > 0) { | 
 | 882 |                 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i]; | 
 | 883 |             } | 
 | 884 |             if (colorOffset > 0) { | 
 | 885 |                 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i]; | 
 | 886 |             } | 
 | 887 |             curVertex = (void*)((intptr_t)curVertex + vsize); | 
 | 888 |         } | 
 | 889 |     } else { | 
 | 890 |         target->setVertexSourceToArray(layout, positions, vertexCount); | 
 | 891 |     } | 
 | 892 |  | 
 | 893 |     if (NULL != indices) { | 
 | 894 |         target->setIndexSourceToArray(indices, indexCount); | 
 | 895 |         target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount); | 
 | 896 |     } else { | 
 | 897 |         target->drawNonIndexed(primitiveType, 0, vertexCount); | 
 | 898 |     } | 
 | 899 | } | 
 | 900 |  | 
 | 901 |  | 
 | 902 | //////////////////////////////////////////////////////////////////////////////// | 
 | 903 |  | 
 | 904 | void GrContext::drawPath(const GrPaint& paint, | 
 | 905 |                          GrPathIter* path, | 
 | 906 |                          GrPathFill fill, | 
 | 907 |                          const GrPoint* translate) { | 
 | 908 |  | 
 | 909 |  | 
 | 910 |     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 911 |  | 
 | 912 |     GrDrawTarget::StageBitfield enabledStages = 0; | 
 | 913 |     if (NULL != paint.getTexture()) { | 
 | 914 |         enabledStages |= 1; | 
 | 915 |     } | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 916 |     GrPathRenderer* pr = getPathRenderer(target, path, fill); | 
 | 917 |     pr->drawPath(target, enabledStages, path, fill, translate); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 918 | } | 
 | 919 |  | 
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 920 | void GrContext::drawPath(const GrPaint& paint, | 
 | 921 |                          const GrPath& path, | 
 | 922 |                          GrPathFill fill, | 
 | 923 |                          const GrPoint* translate) { | 
 | 924 |     GrPath::Iter iter(path); | 
 | 925 |     this->drawPath(paint, &iter, fill, translate); | 
 | 926 | } | 
 | 927 |  | 
 | 928 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 929 | //////////////////////////////////////////////////////////////////////////////// | 
 | 930 |  | 
| bsalomon@google.com | a7f84e1 | 2011-03-10 14:13:19 +0000 | [diff] [blame] | 931 | void GrContext::flush(int flagsBitfield) { | 
 | 932 |     if (kDiscard_FlushBit & flagsBitfield) { | 
 | 933 |         fDrawBuffer->reset(); | 
 | 934 |     } else { | 
 | 935 |         flushDrawBuffer(); | 
 | 936 |     } | 
 | 937 |  | 
 | 938 |     if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) { | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 939 |         fGpu->forceRenderTargetFlush(); | 
 | 940 |     } | 
 | 941 | } | 
 | 942 |  | 
 | 943 | void GrContext::flushText() { | 
 | 944 |     if (kText_DrawCategory == fLastDrawCategory) { | 
 | 945 |         flushDrawBuffer(); | 
 | 946 |     } | 
 | 947 | } | 
 | 948 |  | 
 | 949 | void GrContext::flushDrawBuffer() { | 
 | 950 | #if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING | 
 | 951 |     fDrawBuffer->playback(fGpu); | 
 | 952 |     fDrawBuffer->reset(); | 
 | 953 | #endif | 
 | 954 | } | 
 | 955 |  | 
| bsalomon@google.com | 669fdc4 | 2011-04-05 17:08:27 +0000 | [diff] [blame] | 956 | bool GrContext::readTexturePixels(GrTexture* texture, | 
 | 957 |                                   int left, int top, int width, int height, | 
 | 958 |                                   GrPixelConfig config, void* buffer) { | 
 | 959 |  | 
 | 960 |     // TODO: code read pixels for textures that aren't rendertargets | 
 | 961 |  | 
 | 962 |     this->flush(); | 
 | 963 |     GrRenderTarget* target = texture->asRenderTarget(); | 
 | 964 |     if (NULL != target) { | 
 | 965 |         return fGpu->readPixels(target, | 
 | 966 |                                 left, top, width, height,  | 
 | 967 |                                 config, buffer); | 
 | 968 |     } else { | 
 | 969 |         return false; | 
 | 970 |     } | 
 | 971 | } | 
 | 972 |  | 
 | 973 | bool GrContext::readRenderTargetPixels(GrRenderTarget* target, | 
 | 974 |                                       int left, int top, int width, int height, | 
 | 975 |                                       GrPixelConfig config, void* buffer) { | 
 | 976 |     uint32_t flushFlags = 0; | 
 | 977 |     if (NULL == target) {  | 
 | 978 |         flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit; | 
 | 979 |     } | 
 | 980 |  | 
 | 981 |     this->flush(flushFlags); | 
 | 982 |     return fGpu->readPixels(target, | 
 | 983 |                             left, top, width, height,  | 
 | 984 |                             config, buffer); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 985 | } | 
 | 986 |  | 
 | 987 | void GrContext::writePixels(int left, int top, int width, int height, | 
| bsalomon@google.com | 669fdc4 | 2011-04-05 17:08:27 +0000 | [diff] [blame] | 988 |                             GrPixelConfig config, const void* buffer, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 989 |                             size_t stride) { | 
 | 990 |  | 
 | 991 |     // TODO: when underlying api has a direct way to do this we should use it | 
 | 992 |     // (e.g. glDrawPixels on desktop GL). | 
 | 993 |  | 
| bsalomon@google.com | fea37b5 | 2011-04-25 15:51:06 +0000 | [diff] [blame^] | 994 |     const GrTextureDesc desc = { | 
 | 995 |         kNone_GrTextureFlags, kNone_GrAALevel, width, height, config | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 996 |     }; | 
 | 997 |     GrTexture* texture = fGpu->createTexture(desc, buffer, stride); | 
 | 998 |     if (NULL == texture) { | 
 | 999 |         return; | 
 | 1000 |     } | 
 | 1001 |  | 
 | 1002 |     this->flush(true); | 
 | 1003 |  | 
 | 1004 |     GrAutoUnref                     aur(texture); | 
 | 1005 |     GrDrawTarget::AutoStateRestore  asr(fGpu); | 
 | 1006 |  | 
 | 1007 |     GrMatrix matrix; | 
 | 1008 |     matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); | 
 | 1009 |     fGpu->setViewMatrix(matrix); | 
 | 1010 |  | 
 | 1011 |     fGpu->disableState(GrDrawTarget::kClip_StateBit); | 
 | 1012 |     fGpu->setAlpha(0xFF); | 
 | 1013 |     fGpu->setBlendFunc(kOne_BlendCoeff, | 
 | 1014 |                        kZero_BlendCoeff); | 
 | 1015 |     fGpu->setTexture(0, texture); | 
 | 1016 |  | 
 | 1017 |     GrSamplerState sampler; | 
 | 1018 |     sampler.setClampNoFilter(); | 
 | 1019 |     matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height); | 
 | 1020 |     sampler.setMatrix(matrix); | 
 | 1021 |     fGpu->setSamplerState(0, sampler); | 
 | 1022 |  | 
 | 1023 |     GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); | 
 | 1024 |     static const int VCOUNT = 4; | 
 | 1025 |  | 
 | 1026 |     GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0); | 
 | 1027 |     if (!geo.succeeded()) { | 
 | 1028 |         return; | 
 | 1029 |     } | 
 | 1030 |     ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height); | 
 | 1031 |     fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT); | 
 | 1032 | } | 
 | 1033 | //////////////////////////////////////////////////////////////////////////////// | 
 | 1034 |  | 
 | 1035 | void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) { | 
 | 1036 |     target->setTexture(0, paint.getTexture()); | 
 | 1037 |     target->setSamplerState(0, paint.fSampler); | 
 | 1038 |     target->setColor(paint.fColor); | 
 | 1039 |  | 
 | 1040 |     if (paint.fDither) { | 
 | 1041 |         target->enableState(GrDrawTarget::kDither_StateBit); | 
 | 1042 |     } else { | 
 | 1043 |         target->disableState(GrDrawTarget::kDither_StateBit); | 
 | 1044 |     } | 
 | 1045 |     if (paint.fAntiAlias) { | 
 | 1046 |         target->enableState(GrDrawTarget::kAntialias_StateBit); | 
 | 1047 |     } else { | 
 | 1048 |         target->disableState(GrDrawTarget::kAntialias_StateBit); | 
 | 1049 |     } | 
 | 1050 |     target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); | 
 | 1051 | } | 
 | 1052 |  | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 1053 | GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1054 |                                        DrawCategory category) { | 
 | 1055 |     if (category != fLastDrawCategory) { | 
 | 1056 |         flushDrawBuffer(); | 
 | 1057 |         fLastDrawCategory = category; | 
 | 1058 |     } | 
 | 1059 |     SetPaint(paint, fGpu); | 
 | 1060 |     GrDrawTarget* target = fGpu; | 
 | 1061 |     switch (category) { | 
 | 1062 |     case kText_DrawCategory: | 
 | 1063 | #if DEFER_TEXT_RENDERING | 
 | 1064 |         target = fDrawBuffer; | 
 | 1065 |         fDrawBuffer->initializeDrawStateAndClip(*fGpu); | 
 | 1066 | #else | 
 | 1067 |         target = fGpu; | 
 | 1068 | #endif | 
 | 1069 |         break; | 
 | 1070 |     case kUnbuffered_DrawCategory: | 
 | 1071 |         target = fGpu; | 
 | 1072 |         break; | 
 | 1073 |     case kBuffered_DrawCategory: | 
 | 1074 |         target = fDrawBuffer; | 
 | 1075 |         fDrawBuffer->initializeDrawStateAndClip(*fGpu); | 
 | 1076 |         break; | 
 | 1077 |     } | 
 | 1078 |     return target; | 
 | 1079 | } | 
 | 1080 |  | 
 | 1081 | //////////////////////////////////////////////////////////////////////////////// | 
 | 1082 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1083 | void GrContext::setRenderTarget(GrRenderTarget* target) { | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1084 |     this->flush(false); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1085 |     fGpu->setRenderTarget(target); | 
 | 1086 | } | 
 | 1087 |  | 
 | 1088 | GrRenderTarget* GrContext::getRenderTarget() { | 
 | 1089 |     return fGpu->getRenderTarget(); | 
 | 1090 | } | 
 | 1091 |  | 
 | 1092 | const GrRenderTarget* GrContext::getRenderTarget() const { | 
 | 1093 |     return fGpu->getRenderTarget(); | 
 | 1094 | } | 
 | 1095 |  | 
 | 1096 | const GrMatrix& GrContext::getMatrix() const { | 
 | 1097 |     return fGpu->getViewMatrix(); | 
 | 1098 | } | 
 | 1099 |  | 
 | 1100 | void GrContext::setMatrix(const GrMatrix& m) { | 
 | 1101 |     fGpu->setViewMatrix(m); | 
 | 1102 | } | 
 | 1103 |  | 
 | 1104 | void GrContext::concatMatrix(const GrMatrix& m) const { | 
 | 1105 |     fGpu->preConcatViewMatrix(m); | 
 | 1106 | } | 
 | 1107 |  | 
 | 1108 | static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) { | 
 | 1109 |     intptr_t mask = 1 << shift; | 
 | 1110 |     if (pred) { | 
 | 1111 |         bits |= mask; | 
 | 1112 |     } else { | 
 | 1113 |         bits &= ~mask; | 
 | 1114 |     } | 
 | 1115 |     return bits; | 
 | 1116 | } | 
 | 1117 |  | 
 | 1118 | void GrContext::resetStats() { | 
 | 1119 |     fGpu->resetStats(); | 
 | 1120 | } | 
 | 1121 |  | 
 | 1122 | const GrGpu::Stats& GrContext::getStats() const { | 
 | 1123 |     return fGpu->getStats(); | 
 | 1124 | } | 
 | 1125 |  | 
 | 1126 | void GrContext::printStats() const { | 
 | 1127 |     fGpu->printStats(); | 
 | 1128 | } | 
 | 1129 |  | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 1130 | GrContext::GrContext(GrGpu* gpu) : | 
 | 1131 |     fDefaultPathRenderer(gpu->supportsTwoSidedStencil(), | 
 | 1132 |                          gpu->supportsStencilWrapOps()) { | 
 | 1133 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1134 |     fGpu = gpu; | 
 | 1135 |     fGpu->ref(); | 
| bsalomon@google.com | 669fdc4 | 2011-04-05 17:08:27 +0000 | [diff] [blame] | 1136 |     fGpu->setContext(this); | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1137 |  | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 1138 |     fCustomPathRenderer = GrPathRenderer::CreatePathRenderer(); | 
 | 1139 |     fGpu->setClipPathRenderer(fCustomPathRenderer); | 
 | 1140 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1141 |     fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT, | 
 | 1142 |                                        MAX_TEXTURE_CACHE_BYTES); | 
 | 1143 |     fFontCache = new GrFontCache(fGpu); | 
 | 1144 |  | 
 | 1145 |     fLastDrawCategory = kUnbuffered_DrawCategory; | 
 | 1146 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1147 |     fDrawBuffer = NULL; | 
 | 1148 |     fDrawBufferVBAllocPool = NULL; | 
 | 1149 |     fDrawBufferIBAllocPool = NULL; | 
 | 1150 |  | 
| bsalomon@google.com | 205d460 | 2011-04-25 12:43:45 +0000 | [diff] [blame] | 1151 |     fAAFillRectIndexBuffer = NULL; | 
 | 1152 |     fAAStrokeRectIndexBuffer = NULL; | 
 | 1153 |  | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1154 |     this->setupDrawBuffer(); | 
 | 1155 | } | 
 | 1156 |  | 
 | 1157 | void GrContext::setupDrawBuffer() { | 
 | 1158 |  | 
 | 1159 |     GrAssert(NULL == fDrawBuffer); | 
 | 1160 |     GrAssert(NULL == fDrawBufferVBAllocPool); | 
 | 1161 |     GrAssert(NULL == fDrawBufferIBAllocPool); | 
 | 1162 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1163 | #if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 1164 |     fDrawBufferVBAllocPool = | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1165 |         new GrVertexBufferAllocPool(fGpu, false, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1166 |                                     DRAW_BUFFER_VBPOOL_BUFFER_SIZE, | 
 | 1167 |                                     DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS); | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 1168 |     fDrawBufferIBAllocPool = | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1169 |         new GrIndexBufferAllocPool(fGpu, false, | 
| bsalomon@google.com | de6ac2d | 2011-02-25 21:50:42 +0000 | [diff] [blame] | 1170 |                                    DRAW_BUFFER_IBPOOL_BUFFER_SIZE, | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1171 |                                    DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS); | 
 | 1172 |  | 
 | 1173 |     fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool, | 
 | 1174 |                                           fDrawBufferIBAllocPool); | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1175 | #endif | 
 | 1176 |  | 
 | 1177 | #if BATCH_RECT_TO_RECT | 
 | 1178 |     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer()); | 
 | 1179 | #endif | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1180 | } | 
 | 1181 |  | 
| bsalomon@google.com | 27847de | 2011-02-22 20:59:41 +0000 | [diff] [blame] | 1182 | GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) { | 
 | 1183 |     GrDrawTarget* target; | 
 | 1184 | #if DEFER_TEXT_RENDERING | 
 | 1185 |     target = prepareToDraw(paint, kText_DrawCategory); | 
 | 1186 | #else | 
 | 1187 |     target = prepareToDraw(paint, kUnbuffered_DrawCategory); | 
 | 1188 | #endif | 
 | 1189 |     SetPaint(paint, target); | 
 | 1190 |     return target; | 
 | 1191 | } | 
 | 1192 |  | 
 | 1193 | const GrIndexBuffer* GrContext::getQuadIndexBuffer() const { | 
 | 1194 |     return fGpu->getQuadIndexBuffer(); | 
 | 1195 | } | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 1196 |  | 
 | 1197 | GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, | 
 | 1198 |                                            GrPathIter* path, | 
 | 1199 |                                            GrPathFill fill) { | 
| bsalomon@google.com | 8fe7247 | 2011-03-30 21:26:44 +0000 | [diff] [blame] | 1200 |     if (NULL != fCustomPathRenderer && | 
| bsalomon@google.com | dfe75bc | 2011-03-25 12:31:16 +0000 | [diff] [blame] | 1201 |         fCustomPathRenderer->canDrawPath(target, path, fill)) { | 
 | 1202 |         return fCustomPathRenderer; | 
 | 1203 |     } else { | 
 | 1204 |         GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill)); | 
 | 1205 |         return &fDefaultPathRenderer; | 
 | 1206 |     } | 
 | 1207 | } |