reed@google.com | 873cb1e | 2010-12-23 15:00:45 +0000 | [diff] [blame] | 1 | /*
|
| 2 | Copyright 2010 Google Inc.
|
| 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 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 17 | #include "GrContext.h"
|
bsalomon@google.com | 7acdb8e | 2011-02-11 14:07:02 +0000 | [diff] [blame] | 18 | #include "GrTypes.h"
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 19 | #include "GrTextureCache.h"
|
| 20 | #include "GrTextStrike.h"
|
| 21 | #include "GrMemory.h"
|
| 22 | #include "GrPathIter.h"
|
| 23 | #include "GrClipIterator.h"
|
| 24 | #include "GrIndexBuffer.h"
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 25 | #include "GrInOrderDrawBuffer.h"
|
| 26 | #include "GrBufferAllocPool.h"
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 27 | #include "GrPathRenderer.h"
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 28 |
|
| 29 | #define DEFER_TEXT_RENDERING 1
|
| 30 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 31 | #define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
|
| 32 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 33 | static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
|
| 34 | static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
|
| 35 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 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;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 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 |
|
reed@google.com | 873cb1e | 2010-12-23 15:00:45 +0000 | [diff] [blame] | 55 | GrContext* GrContext::CreateGLShaderContext() {
|
| 56 | return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
|
| 57 | }
|
| 58 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 59 | GrContext::~GrContext() {
|
| 60 | fGpu->unref();
|
| 61 | delete fTextureCache;
|
| 62 | delete fFontCache;
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 63 | delete fDrawBuffer;
|
| 64 | delete fDrawBufferVBAllocPool;
|
| 65 | delete fDrawBufferVBAllocPool;
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 66 | delete fPathRenderer;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 67 | }
|
| 68 |
|
| 69 | void GrContext::abandonAllTextures() {
|
| 70 | fTextureCache->deleteAll(GrTextureCache::kAbandonTexture_DeleteMode);
|
| 71 | fFontCache->abandonAll();
|
| 72 | }
|
| 73 |
|
| 74 | GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
|
| 75 | const GrSamplerState& sampler) {
|
| 76 | finalizeTextureKey(key, sampler);
|
| 77 | return fTextureCache->findAndLock(*key);
|
| 78 | }
|
| 79 |
|
| 80 | static void stretchImage(void* dst,
|
| 81 | int dstW,
|
| 82 | int dstH,
|
| 83 | void* src,
|
| 84 | int srcW,
|
| 85 | int srcH,
|
| 86 | int bpp) {
|
| 87 | GrFixed dx = (srcW << 16) / dstW;
|
| 88 | GrFixed dy = (srcH << 16) / dstH;
|
| 89 |
|
| 90 | GrFixed y = dy >> 1;
|
| 91 |
|
| 92 | int dstXLimit = dstW*bpp;
|
| 93 | for (int j = 0; j < dstH; ++j) {
|
| 94 | GrFixed x = dx >> 1;
|
| 95 | void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
|
| 96 | void* dstRow = (uint8_t*)dst + j*dstW*bpp;
|
| 97 | for (int i = 0; i < dstXLimit; i += bpp) {
|
| 98 | memcpy((uint8_t*) dstRow + i,
|
| 99 | (uint8_t*) srcRow + (x>>16)*bpp,
|
| 100 | bpp);
|
| 101 | x += dx;
|
| 102 | }
|
| 103 | y += dy;
|
| 104 | }
|
| 105 | }
|
| 106 |
|
| 107 | GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
|
| 108 | const GrSamplerState& sampler,
|
| 109 | const GrGpu::TextureDesc& desc,
|
| 110 | void* srcData, size_t rowBytes) {
|
| 111 | GrAssert(key->width() == desc.fWidth);
|
| 112 | GrAssert(key->height() == desc.fHeight);
|
| 113 |
|
| 114 | #if GR_DUMP_TEXTURE_UPLOAD
|
| 115 | GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
|
| 116 | #endif
|
| 117 |
|
| 118 | GrTextureEntry* entry = NULL;
|
| 119 | bool special = finalizeTextureKey(key, sampler);
|
| 120 | if (special) {
|
| 121 | GrTextureEntry* clampEntry;
|
| 122 | GrTextureKey clampKey(*key);
|
| 123 | clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
|
| 124 |
|
| 125 | if (NULL == clampEntry) {
|
| 126 | clampEntry = createAndLockTexture(&clampKey,
|
| 127 | GrSamplerState::ClampNoFilter(),
|
| 128 | desc, srcData, rowBytes);
|
| 129 | GrAssert(NULL != clampEntry);
|
| 130 | if (NULL == clampEntry) {
|
| 131 | return NULL;
|
| 132 | }
|
| 133 | }
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 134 | GrGpu::TextureDesc rtDesc = desc;
|
| 135 | rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
|
| 136 | GrGpu::kNoPathRendering_TextureFlag;
|
| 137 | rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
|
| 138 | fGpu->minRenderTargetWidth()));
|
| 139 | rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
|
| 140 | fGpu->minRenderTargetHeight()));
|
| 141 |
|
| 142 | GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
|
| 143 |
|
| 144 | if (NULL != texture) {
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 145 | GrDrawTarget::AutoStateRestore asr(fGpu);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 146 | fGpu->setRenderTarget(texture->asRenderTarget());
|
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame] | 147 | fGpu->setTexture(0, clampEntry->texture());
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 148 | fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 149 | fGpu->setViewMatrix(GrMatrix::I());
|
| 150 | fGpu->setAlpha(0xff);
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 151 | fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 152 | fGpu->disableState(GrDrawTarget::kDither_StateBit |
|
| 153 | GrDrawTarget::kClip_StateBit |
|
| 154 | GrDrawTarget::kAntialias_StateBit);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 155 | GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
|
| 156 | GrSamplerState::kClamp_WrapMode,
|
| 157 | sampler.isFilter());
|
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame] | 158 | fGpu->setSamplerState(0, stretchSampler);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 159 |
|
| 160 | static const GrVertexLayout layout =
|
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame] | 161 | GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 162 | GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
|
| 163 |
|
| 164 | if (arg.succeeded()) {
|
| 165 | GrPoint* verts = (GrPoint*) arg.vertices();
|
| 166 | verts[0].setIRectFan(0, 0,
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 167 | texture->width(),
|
| 168 | texture->height(),
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 169 | 2*sizeof(GrPoint));
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 170 | verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 171 | fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 172 | 0, 4);
|
| 173 | entry = fTextureCache->createAndLock(*key, texture);
|
| 174 | }
|
| 175 | texture->removeRenderTarget();
|
| 176 | } else {
|
| 177 | // TODO: Our CPU stretch doesn't filter. But we create separate
|
| 178 | // stretched textures when the sampler state is either filtered or
|
| 179 | // not. Either implement filtered stretch blit on CPU or just create
|
| 180 | // one when FBO case fails.
|
| 181 |
|
| 182 | rtDesc.fFlags = 0;
|
| 183 | // no longer need to clamp at min RT size.
|
| 184 | rtDesc.fWidth = GrNextPow2(desc.fWidth);
|
| 185 | rtDesc.fHeight = GrNextPow2(desc.fHeight);
|
| 186 | int bpp = GrTexture::BytesPerPixel(desc.fFormat);
|
| 187 | GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
|
| 188 | rtDesc.fWidth *
|
| 189 | rtDesc.fHeight);
|
| 190 | stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
|
| 191 | srcData, desc.fWidth, desc.fHeight, bpp);
|
| 192 |
|
| 193 | size_t stretchedRowBytes = rtDesc.fWidth * bpp;
|
| 194 |
|
| 195 | GrTexture* texture = fGpu->createTexture(rtDesc,
|
| 196 | stretchedPixels.get(),
|
| 197 | stretchedRowBytes);
|
| 198 | GrAssert(NULL != texture);
|
| 199 | entry = fTextureCache->createAndLock(*key, texture);
|
| 200 | }
|
| 201 | fTextureCache->unlock(clampEntry);
|
| 202 |
|
| 203 | } else {
|
| 204 | GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
|
| 205 | if (NULL != texture) {
|
| 206 | entry = fTextureCache->createAndLock(*key, texture);
|
| 207 | } else {
|
| 208 | entry = NULL;
|
| 209 | }
|
| 210 | }
|
| 211 | return entry;
|
| 212 | }
|
| 213 |
|
| 214 | void GrContext::unlockTexture(GrTextureEntry* entry) {
|
| 215 | fTextureCache->unlock(entry);
|
| 216 | }
|
| 217 |
|
| 218 | void GrContext::detachCachedTexture(GrTextureEntry* entry) {
|
| 219 | fTextureCache->detach(entry);
|
| 220 | }
|
| 221 |
|
| 222 | void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
|
| 223 | fTextureCache->reattachAndUnlock(entry);
|
| 224 | }
|
| 225 |
|
| 226 | GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
|
| 227 | void* srcData,
|
| 228 | size_t rowBytes) {
|
| 229 | return fGpu->createTexture(desc, srcData, rowBytes);
|
| 230 | }
|
| 231 |
|
reed@google.com | 01804b4 | 2011-01-18 21:50:41 +0000 | [diff] [blame] | 232 | void GrContext::getTextureCacheLimits(int* maxTextures,
|
| 233 | size_t* maxTextureBytes) const {
|
| 234 | fTextureCache->getLimits(maxTextures, maxTextureBytes);
|
| 235 | }
|
| 236 |
|
| 237 | void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
|
| 238 | fTextureCache->setLimits(maxTextures, maxTextureBytes);
|
| 239 | }
|
| 240 |
|
reed@google.com | 02a7e6c | 2011-01-28 21:21:49 +0000 | [diff] [blame] | 241 | int GrContext::getMaxTextureDimension() {
|
| 242 | return fGpu->maxTextureDimension();
|
| 243 | }
|
| 244 |
|
reed@google.com | 01804b4 | 2011-01-18 21:50:41 +0000 | [diff] [blame] | 245 | ///////////////////////////////////////////////////////////////////////////////
|
| 246 |
|
bsalomon@google.com | 8895a7a | 2011-02-18 16:09:55 +0000 | [diff] [blame] | 247 | GrRenderTarget* GrContext::createPlatformRenderTarget(
|
| 248 | intptr_t platformRenderTarget,
|
| 249 | int stencilBits,
|
| 250 | int width, int height) {
|
| 251 | return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 252 | width, height);
|
| 253 | }
|
| 254 |
|
| 255 | bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
|
| 256 | int width, int height) {
|
| 257 | if (!fGpu->supports8BitPalette()) {
|
| 258 | return false;
|
| 259 | }
|
| 260 |
|
bsalomon@google.com | 0748f21 | 2011-02-01 22:56:16 +0000 | [diff] [blame] | 261 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 262 | bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
| 263 |
|
bsalomon@google.com | 0748f21 | 2011-02-01 22:56:16 +0000 | [diff] [blame] | 264 | if (!isPow2) {
|
| 265 | if (!fGpu->npotTextureSupport()) {
|
| 266 | return false;
|
| 267 | }
|
| 268 |
|
| 269 | bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
|
| 270 | sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
|
| 271 | if (tiled && !fGpu->npotTextureTileSupport()) {
|
| 272 | return false;
|
| 273 | }
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 274 | }
|
bsalomon@google.com | 0748f21 | 2011-02-01 22:56:16 +0000 | [diff] [blame] | 275 | return true;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 276 | }
|
| 277 |
|
| 278 | ////////////////////////////////////////////////////////////////////////////////
|
| 279 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 280 | void GrContext::setClip(const GrClip& clip) {
|
| 281 | fGpu->setClip(clip);
|
| 282 | fGpu->enableState(GrDrawTarget::kClip_StateBit);
|
| 283 | }
|
| 284 |
|
| 285 | void GrContext::setClip(const GrIRect& rect) {
|
| 286 | GrClip clip;
|
| 287 | clip.setRect(rect);
|
| 288 | fGpu->setClip(clip);
|
| 289 | }
|
| 290 |
|
| 291 | ////////////////////////////////////////////////////////////////////////////////
|
| 292 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 293 | void GrContext::eraseColor(GrColor color) {
|
| 294 | fGpu->eraseColor(color);
|
| 295 | }
|
| 296 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 297 | void GrContext::drawPaint(const GrPaint& paint) {
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 298 | // set rect to be big enough to fill the space, but not super-huge, so we
|
| 299 | // don't overflow fixed-point implementations
|
| 300 | GrRect r(fGpu->getClip().getBounds());
|
| 301 | GrMatrix inverse;
|
| 302 | if (fGpu->getViewInverse(&inverse)) {
|
| 303 | inverse.mapRect(&r);
|
| 304 | } else {
|
| 305 | GrPrintf("---- fGpu->getViewInverse failed\n");
|
| 306 | }
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 307 | this->drawRect(paint, r);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 308 | }
|
| 309 |
|
| 310 | /* create a triangle strip that strokes the specified triangle. There are 8
|
| 311 | unique vertices, but we repreat the last 2 to close up. Alternatively we
|
| 312 | could use an indices array, and then only send 8 verts, but not sure that
|
| 313 | would be faster.
|
| 314 | */
|
| 315 | static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
|
| 316 | GrScalar width) {
|
| 317 | const GrScalar rad = GrScalarHalf(width);
|
| 318 |
|
| 319 | verts[0].set(rect.fLeft + rad, rect.fTop + rad);
|
| 320 | verts[1].set(rect.fLeft - rad, rect.fTop - rad);
|
| 321 | verts[2].set(rect.fRight - rad, rect.fTop + rad);
|
| 322 | verts[3].set(rect.fRight + rad, rect.fTop - rad);
|
| 323 | verts[4].set(rect.fRight - rad, rect.fBottom - rad);
|
| 324 | verts[5].set(rect.fRight + rad, rect.fBottom + rad);
|
| 325 | verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
|
| 326 | verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
|
| 327 | verts[8] = verts[0];
|
| 328 | verts[9] = verts[1];
|
| 329 | }
|
| 330 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 331 | void GrContext::drawRect(const GrPaint& paint,
|
| 332 | const GrRect& rect,
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 333 | GrScalar width,
|
| 334 | const GrMatrix* matrix) {
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 335 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 336 | bool textured = NULL != paint.getTexture();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 337 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 338 | GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 339 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 340 | if (width >= 0) {
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 341 | // TODO: consider making static vertex buffers for these cases.
|
bsalomon@google.com | 7acdb8e | 2011-02-11 14:07:02 +0000 | [diff] [blame] | 342 | // Hairline could be done by just adding closing vertex to
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 343 | // unitSquareVertexBuffer()
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 344 | GrVertexLayout layout = (textured) ?
|
| 345 | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
|
| 346 | 0;
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 347 | static const int worstCaseVertCount = 10;
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 348 | GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 349 |
|
| 350 | if (!geo.succeeded()) {
|
| 351 | return;
|
| 352 | }
|
| 353 |
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 354 | GrPrimitiveType primType;
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 355 | int vertCount;
|
| 356 | GrPoint* vertex = geo.positions();
|
| 357 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 358 | if (width > 0) {
|
| 359 | vertCount = 10;
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 360 | primType = kTriangleStrip_PrimitiveType;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 361 | setStrokeRectStrip(vertex, rect, width);
|
| 362 | } else {
|
| 363 | // hairline
|
| 364 | vertCount = 5;
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 365 | primType = kLineStrip_PrimitiveType;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 366 | vertex[0].set(rect.fLeft, rect.fTop);
|
| 367 | vertex[1].set(rect.fRight, rect.fTop);
|
| 368 | vertex[2].set(rect.fRight, rect.fBottom);
|
| 369 | vertex[3].set(rect.fLeft, rect.fBottom);
|
| 370 | vertex[4].set(rect.fLeft, rect.fTop);
|
| 371 | }
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 372 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 373 | GrDrawTarget::AutoViewMatrixRestore avmr;
|
| 374 | if (NULL != matrix) {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 375 | avmr.set(target);
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 376 | target->preConcatViewMatrix(*matrix);
|
| 377 | target->preConcatSamplerMatrix(0, *matrix);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 378 | }
|
| 379 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 380 | target->drawNonIndexed(primType, 0, vertCount);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 381 | } else {
|
bsalomon@google.com | 4333323 | 2011-02-02 19:24:54 +0000 | [diff] [blame] | 382 | #if GR_STATIC_RECT_VB
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 383 | GrVertexLayout layout = (textured) ?
|
| 384 | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
|
| 385 | 0;
|
| 386 | target->setVertexSourceToBuffer(layout,
|
| 387 | fGpu->getUnitSquareVertexBuffer());
|
| 388 | GrDrawTarget::AutoViewMatrixRestore avmr(target);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 389 | GrMatrix m;
|
| 390 | m.setAll(rect.width(), 0, rect.fLeft,
|
| 391 | 0, rect.height(), rect.fTop,
|
| 392 | 0, 0, GrMatrix::I()[8]);
|
bsalomon@google.com | 7acdb8e | 2011-02-11 14:07:02 +0000 | [diff] [blame] | 393 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 394 | if (NULL != matrix) {
|
| 395 | m.postConcat(*matrix);
|
| 396 | }
|
| 397 |
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 398 | target->preConcatViewMatrix(m);
|
bsalomon@google.com | 7acdb8e | 2011-02-11 14:07:02 +0000 | [diff] [blame] | 399 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 400 | if (textured) {
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 401 | target->preConcatSamplerMatrix(0, m);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 402 | }
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 403 | target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 404 | #else
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 405 | target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 406 | #endif
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 407 | }
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 408 | }
|
| 409 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 410 | void GrContext::drawRectToRect(const GrPaint& paint,
|
| 411 | const GrRect& dstRect,
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 412 | const GrRect& srcRect,
|
| 413 | const GrMatrix* dstMatrix,
|
| 414 | const GrMatrix* srcMatrix) {
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 415 |
|
| 416 | if (NULL == paint.getTexture()) {
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 417 | drawRect(paint, dstRect, -1, dstMatrix);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 418 | return;
|
| 419 | }
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 420 |
|
| 421 | GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 422 |
|
bsalomon@google.com | 4333323 | 2011-02-02 19:24:54 +0000 | [diff] [blame] | 423 | #if GR_STATIC_RECT_VB
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 424 | GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
|
| 425 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 426 | GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 427 | GrDrawTarget::AutoViewMatrixRestore avmr(target);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 428 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 429 | GrMatrix m;
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 430 |
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 431 | m.setAll(dstRect.width(), 0, dstRect.fLeft,
|
| 432 | 0, dstRect.height(), dstRect.fTop,
|
| 433 | 0, 0, GrMatrix::I()[8]);
|
| 434 | if (NULL != dstMatrix) {
|
| 435 | m.postConcat(*dstMatrix);
|
| 436 | }
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 437 | target->preConcatViewMatrix(m);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 438 |
|
| 439 | m.setAll(srcRect.width(), 0, srcRect.fLeft,
|
| 440 | 0, srcRect.height(), srcRect.fTop,
|
| 441 | 0, 0, GrMatrix::I()[8]);
|
| 442 | if (NULL != srcMatrix) {
|
| 443 | m.postConcat(*srcMatrix);
|
| 444 | }
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 445 | target->preConcatSamplerMatrix(0, m);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 446 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 447 | target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 448 | target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 449 | #else
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 450 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 451 | GrDrawTarget* target;
|
| 452 | #if BATCH_RECT_TO_RECT
|
| 453 | target = this->prepareToDraw(paint, kBuffered_DrawCategory);
|
| 454 | #else
|
| 455 | target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
|
bsalomon@google.com | 6f7fbc9 | 2011-02-01 19:12:40 +0000 | [diff] [blame] | 456 | #endif
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 457 |
|
| 458 | const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
|
| 459 | const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
|
| 460 | srcRects[0] = &srcRect;
|
| 461 | srcMatrices[0] = srcMatrix;
|
| 462 |
|
| 463 | target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
|
| 464 | #endif
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 465 | }
|
| 466 |
|
| 467 | void GrContext::drawVertices(const GrPaint& paint,
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 468 | GrPrimitiveType primitiveType,
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 469 | int vertexCount,
|
| 470 | const GrPoint positions[],
|
| 471 | const GrPoint texCoords[],
|
| 472 | const GrColor colors[],
|
| 473 | const uint16_t indices[],
|
| 474 | int indexCount) {
|
| 475 | GrVertexLayout layout = 0;
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 476 | int vertexSize = sizeof(GrPoint);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 477 |
|
| 478 | GrDrawTarget::AutoReleaseGeometry geo;
|
| 479 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 480 | GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 481 |
|
| 482 | if (NULL != paint.getTexture()) {
|
| 483 | if (NULL == texCoords) {
|
| 484 | layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
|
| 485 | } else {
|
| 486 | layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 487 | vertexSize += sizeof(GrPoint);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 488 | }
|
| 489 | }
|
| 490 |
|
| 491 | if (NULL != colors) {
|
| 492 | layout |= GrDrawTarget::kColor_VertexLayoutBit;
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 493 | vertexSize += sizeof(GrColor);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 494 | }
|
| 495 |
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 496 | if (sizeof(GrPoint) != vertexSize) {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 497 | if (!geo.set(target, layout, vertexCount, 0)) {
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 498 | GrPrintf("Failed to get space for vertices!");
|
| 499 | return;
|
| 500 | }
|
| 501 | int texOffsets[GrDrawTarget::kMaxTexCoords];
|
| 502 | int colorOffset;
|
| 503 | int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
|
| 504 | texOffsets,
|
| 505 | &colorOffset);
|
| 506 | void* curVertex = geo.vertices();
|
| 507 |
|
| 508 | for (int i = 0; i < vertexCount; ++i) {
|
| 509 | *((GrPoint*)curVertex) = positions[i];
|
| 510 |
|
| 511 | if (texOffsets[0] > 0) {
|
| 512 | *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
|
| 513 | }
|
| 514 | if (colorOffset > 0) {
|
| 515 | *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
|
| 516 | }
|
| 517 | curVertex = (void*)((intptr_t)curVertex + vsize);
|
| 518 | }
|
| 519 | } else {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 520 | target->setVertexSourceToArray(layout, positions, vertexCount);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 521 | }
|
| 522 |
|
| 523 | if (NULL != indices) {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 524 | target->setIndexSourceToArray(indices, indexCount);
|
| 525 | target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 526 | } else {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 527 | target->drawNonIndexed(primitiveType, 0, vertexCount);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 528 | }
|
| 529 | }
|
| 530 |
|
| 531 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 532 | ////////////////////////////////////////////////////////////////////////////////
|
| 533 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 534 | void GrContext::drawPath(const GrPaint& paint,
|
| 535 | GrPathIter* path,
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 536 | GrPathFill fill,
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 537 | const GrPoint* translate) {
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 538 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 539 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 540 | GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 541 |
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 542 | GrDrawTarget::StageBitfield enabledStages = 0;
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 543 | if (NULL != paint.getTexture()) {
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 544 | enabledStages |= 1;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 545 | }
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 546 | fPathRenderer->drawPath(target, enabledStages, path, fill, translate);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 547 | }
|
| 548 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 549 | ////////////////////////////////////////////////////////////////////////////////
|
| 550 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 551 | void GrContext::flush(bool flushRenderTarget) {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 552 | flushDrawBuffer();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 553 | if (flushRenderTarget) {
|
| 554 | fGpu->forceRenderTargetFlush();
|
| 555 | }
|
| 556 | }
|
| 557 |
|
| 558 | void GrContext::flushText() {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 559 | if (kText_DrawCategory == fLastDrawCategory) {
|
| 560 | flushDrawBuffer();
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 561 | }
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 562 | }
|
| 563 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 564 | void GrContext::flushDrawBuffer() {
|
| 565 | #if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
|
| 566 | fDrawBuffer->playback(fGpu);
|
| 567 | fDrawBuffer->reset();
|
| 568 | #endif
|
| 569 | }
|
| 570 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 571 | bool GrContext::readPixels(int left, int top, int width, int height,
|
| 572 | GrTexture::PixelConfig config, void* buffer) {
|
| 573 | this->flush(true);
|
| 574 | return fGpu->readPixels(left, top, width, height, config, buffer);
|
| 575 | }
|
| 576 |
|
| 577 | void GrContext::writePixels(int left, int top, int width, int height,
|
| 578 | GrTexture::PixelConfig config, const void* buffer,
|
| 579 | size_t stride) {
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 580 |
|
| 581 | // TODO: when underlying api has a direct way to do this we should use it
|
| 582 | // (e.g. glDrawPixels on desktop GL).
|
| 583 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 584 | const GrGpu::TextureDesc desc = {
|
| 585 | 0, GrGpu::kNone_AALevel, width, height, config
|
| 586 | };
|
| 587 | GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
|
| 588 | if (NULL == texture) {
|
| 589 | return;
|
| 590 | }
|
| 591 |
|
| 592 | this->flush(true);
|
| 593 |
|
| 594 | GrAutoUnref aur(texture);
|
| 595 | GrDrawTarget::AutoStateRestore asr(fGpu);
|
| 596 |
|
| 597 | GrMatrix matrix;
|
| 598 | matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
|
| 599 | fGpu->setViewMatrix(matrix);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 600 |
|
| 601 | fGpu->disableState(GrDrawTarget::kClip_StateBit);
|
| 602 | fGpu->setAlpha(0xFF);
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 603 | fGpu->setBlendFunc(kOne_BlendCoeff,
|
| 604 | kZero_BlendCoeff);
|
bsalomon@google.com | 8531c1c | 2011-01-13 19:52:45 +0000 | [diff] [blame] | 605 | fGpu->setTexture(0, texture);
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 606 |
|
| 607 | GrSamplerState sampler;
|
| 608 | sampler.setClampNoFilter();
|
| 609 | matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);
|
| 610 | sampler.setMatrix(matrix);
|
| 611 | fGpu->setSamplerState(0, sampler);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 612 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 613 | GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
|
| 614 | static const int VCOUNT = 4;
|
| 615 |
|
| 616 | GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
|
| 617 | if (!geo.succeeded()) {
|
| 618 | return;
|
| 619 | }
|
| 620 | ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 621 | fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 622 | }
|
| 623 | ////////////////////////////////////////////////////////////////////////////////
|
| 624 |
|
| 625 | void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
|
| 626 | target->setTexture(0, paint.getTexture());
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 627 | target->setSamplerState(0, paint.fSampler);
|
| 628 | target->setColor(paint.fColor);
|
| 629 |
|
| 630 | if (paint.fDither) {
|
| 631 | target->enableState(GrDrawTarget::kDither_StateBit);
|
| 632 | } else {
|
| 633 | target->disableState(GrDrawTarget::kDither_StateBit);
|
| 634 | }
|
| 635 | if (paint.fAntiAlias) {
|
| 636 | target->enableState(GrDrawTarget::kAntialias_StateBit);
|
| 637 | } else {
|
| 638 | target->disableState(GrDrawTarget::kAntialias_StateBit);
|
| 639 | }
|
| 640 | target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
|
| 641 | }
|
| 642 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 643 | GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
|
| 644 | DrawCategory category) {
|
| 645 | if (category != fLastDrawCategory) {
|
| 646 | flushDrawBuffer();
|
| 647 | fLastDrawCategory = category;
|
| 648 | }
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 649 | SetPaint(paint, fGpu);
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 650 | GrDrawTarget* target = fGpu;
|
| 651 | switch (category) {
|
| 652 | case kText_DrawCategory:
|
| 653 | #if DEFER_TEXT_RENDERING
|
| 654 | target = fDrawBuffer;
|
| 655 | fDrawBuffer->initializeDrawStateAndClip(*fGpu);
|
| 656 | #else
|
| 657 | target = fGpu;
|
| 658 | #endif
|
| 659 | break;
|
| 660 | case kUnbuffered_DrawCategory:
|
| 661 | target = fGpu;
|
| 662 | break;
|
| 663 | case kBuffered_DrawCategory:
|
| 664 | target = fDrawBuffer;
|
| 665 | fDrawBuffer->initializeDrawStateAndClip(*fGpu);
|
| 666 | break;
|
| 667 | }
|
| 668 | return target;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 669 | }
|
| 670 |
|
| 671 | ////////////////////////////////////////////////////////////////////////////////
|
| 672 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 673 | void GrContext::resetContext() {
|
| 674 | fGpu->resetContext();
|
| 675 | }
|
| 676 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 677 | void GrContext::setRenderTarget(GrRenderTarget* target) {
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 678 | flush(false);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 679 | fGpu->setRenderTarget(target);
|
| 680 | }
|
| 681 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 682 | GrRenderTarget* GrContext::getRenderTarget() {
|
| 683 | return fGpu->getRenderTarget();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 684 | }
|
| 685 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 686 | const GrRenderTarget* GrContext::getRenderTarget() const {
|
| 687 | return fGpu->getRenderTarget();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 688 | }
|
| 689 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 690 | const GrMatrix& GrContext::getMatrix() const {
|
| 691 | return fGpu->getViewMatrix();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 692 | }
|
| 693 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 694 | void GrContext::setMatrix(const GrMatrix& m) {
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 695 | fGpu->setViewMatrix(m);
|
| 696 | }
|
| 697 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 698 | void GrContext::concatMatrix(const GrMatrix& m) const {
|
bsalomon@google.com | c6cf723 | 2011-02-17 16:43:10 +0000 | [diff] [blame] | 699 | fGpu->preConcatViewMatrix(m);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 700 | }
|
| 701 |
|
| 702 | static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
|
| 703 | intptr_t mask = 1 << shift;
|
| 704 | if (pred) {
|
| 705 | bits |= mask;
|
| 706 | } else {
|
| 707 | bits &= ~mask;
|
| 708 | }
|
| 709 | return bits;
|
| 710 | }
|
| 711 |
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 712 | void GrContext::resetStats() {
|
| 713 | fGpu->resetStats();
|
| 714 | }
|
| 715 |
|
| 716 | const GrGpu::Stats& GrContext::getStats() const {
|
| 717 | return fGpu->getStats();
|
| 718 | }
|
| 719 |
|
| 720 | void GrContext::printStats() const {
|
| 721 | fGpu->printStats();
|
| 722 | }
|
| 723 |
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 724 | GrContext::GrContext(GrGpu* gpu) {
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 725 | fGpu = gpu;
|
| 726 | fGpu->ref();
|
| 727 | fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
|
| 728 | MAX_TEXTURE_CACHE_BYTES);
|
| 729 | fFontCache = new GrFontCache(fGpu);
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 730 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 731 | fLastDrawCategory = kUnbuffered_DrawCategory;
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 732 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 733 | #if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
|
| 734 | fDrawBufferVBAllocPool =
|
| 735 | new GrVertexBufferAllocPool(gpu, false,
|
| 736 | DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
|
| 737 | DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
|
| 738 | fDrawBufferIBAllocPool =
|
| 739 | new GrIndexBufferAllocPool(gpu, false,
|
| 740 | DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
|
| 741 | DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
|
| 742 |
|
| 743 | fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
|
| 744 | fDrawBufferIBAllocPool);
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 745 | #else
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 746 | fDrawBuffer = NULL;
|
| 747 | fDrawBufferVBAllocPool = NULL;
|
| 748 | fDrawBufferIBAllocPool = NULL;
|
| 749 | #endif
|
| 750 |
|
| 751 | #if BATCH_RECT_TO_RECT
|
| 752 | fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
|
bsalomon@google.com | 1c13c96 | 2011-02-14 16:51:21 +0000 | [diff] [blame] | 753 | #endif
|
bsalomon@google.com | ffca400 | 2011-02-22 20:34:01 +0000 | [diff] [blame] | 754 | fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 755 | }
|
| 756 |
|
| 757 | bool GrContext::finalizeTextureKey(GrTextureKey* key,
|
| 758 | const GrSamplerState& sampler) const {
|
| 759 | uint32_t bits = 0;
|
| 760 | uint16_t width = key->width();
|
| 761 | uint16_t height = key->height();
|
bsalomon@google.com | 7acdb8e | 2011-02-11 14:07:02 +0000 | [diff] [blame] | 762 |
|
bsalomon@google.com | 0748f21 | 2011-02-01 22:56:16 +0000 | [diff] [blame] | 763 |
|
| 764 | if (!fGpu->npotTextureTileSupport()) {
|
| 765 | bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
| 766 |
|
| 767 | bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
|
| 768 | (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
|
| 769 |
|
| 770 | if (tiled && !isPow2) {
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 771 | bits |= 1;
|
| 772 | bits |= sampler.isFilter() ? 2 : 0;
|
| 773 | }
|
| 774 | }
|
| 775 | key->finalize(bits);
|
| 776 | return 0 != bits;
|
| 777 | }
|
| 778 |
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 779 | GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
|
| 780 | GrDrawTarget* target;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 781 | #if DEFER_TEXT_RENDERING
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 782 | target = prepareToDraw(paint, kText_DrawCategory);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 783 | #else
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 784 | target = prepareToDraw(paint, kUnbuffered_DrawCategory);
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 785 | #endif
|
bsalomon@google.com | 5782d71 | 2011-01-21 21:03:59 +0000 | [diff] [blame] | 786 | SetPaint(paint, target);
|
| 787 | return target;
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 788 | }
|
| 789 |
|
bsalomon@google.com | 86afc2a | 2011-02-16 16:12:19 +0000 | [diff] [blame] | 790 | const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
|
| 791 | return fGpu->getQuadIndexBuffer();
|
reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 792 | }
|