OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrContext.h" | 9 #include "GrContext.h" |
10 | 10 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 if (fGpu->caps()->pathRenderingSupport() && renderTarget->getStencilBuffer()
&& | 216 if (fGpu->caps()->pathRenderingSupport() && renderTarget->getStencilBuffer()
&& |
217 renderTarget->isMultisampled())
{ | 217 renderTarget->isMultisampled())
{ |
218 return GrStencilAndCoverTextContext::Create(this, leakyProperties); | 218 return GrStencilAndCoverTextContext::Create(this, leakyProperties); |
219 } | 219 } |
220 | 220 |
221 return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDista
nceFieldFonts); | 221 return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDista
nceFieldFonts); |
222 } | 222 } |
223 | 223 |
224 //////////////////////////////////////////////////////////////////////////////// | 224 //////////////////////////////////////////////////////////////////////////////// |
225 | 225 |
226 static void stretch_image(void* dst, | 226 GrTexture* GrContext::createTexture(const GrSurfaceDesc& desc, const void* srcDa
ta, |
227 int dstW, | 227 size_t rowBytes) { |
228 int dstH, | 228 return fGpu->createTexture(desc, true, srcData, rowBytes); |
229 const void* src, | |
230 int srcW, | |
231 int srcH, | |
232 size_t bpp) { | |
233 SkFixed dx = (srcW << 16) / dstW; | |
234 SkFixed dy = (srcH << 16) / dstH; | |
235 | |
236 SkFixed y = dy >> 1; | |
237 | |
238 size_t dstXLimit = dstW*bpp; | |
239 for (int j = 0; j < dstH; ++j) { | |
240 SkFixed x = dx >> 1; | |
241 const uint8_t* srcRow = reinterpret_cast<const uint8_t *>(src) + (y>>16)
*srcW*bpp; | |
242 uint8_t* dstRow = reinterpret_cast<uint8_t *>(dst) + j*dstW*bpp; | |
243 for (size_t i = 0; i < dstXLimit; i += bpp) { | |
244 memcpy(dstRow + i, srcRow + (x>>16)*bpp, bpp); | |
245 x += dx; | |
246 } | |
247 y += dy; | |
248 } | |
249 } | |
250 | |
251 enum ResizeFlags { | |
252 /** | |
253 * The kStretchToPOT bit is set when the texture is NPOT and is being repeat
ed or mipped but the | |
254 * hardware doesn't support that feature. | |
255 */ | |
256 kStretchToPOT_ResizeFlag = 0x1, | |
257 /** | |
258 * The kBilerp bit can only be set when the kStretchToPOT flag is set and in
dicates whether the | |
259 * stretched texture should be bilerped. | |
260 */ | |
261 kBilerp_ResizeFlag = 0x2, | |
262 }; | |
263 | |
264 static uint32_t get_texture_flags(const GrGpu* gpu, | |
265 const GrTextureParams* params, | |
266 const GrSurfaceDesc& desc) { | |
267 uint32_t flags = 0; | |
268 bool tiled = params && params->isTiled(); | |
269 if (tiled && !gpu->caps()->npotTextureTileSupport()) { | |
270 if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) { | |
271 flags |= kStretchToPOT_ResizeFlag; | |
272 switch(params->filterMode()) { | |
273 case GrTextureParams::kNone_FilterMode: | |
274 break; | |
275 case GrTextureParams::kBilerp_FilterMode: | |
276 case GrTextureParams::kMipMap_FilterMode: | |
277 flags |= kBilerp_ResizeFlag; | |
278 break; | |
279 } | |
280 } | |
281 } | |
282 return flags; | |
283 } | |
284 // The desired texture is NPOT and tiled but that isn't supported by | |
285 // the current hardware. Resize the texture to be a POT | |
286 GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, | |
287 const GrContentKey& origKey, | |
288 const void* srcData, | |
289 size_t rowBytes, | |
290 bool filter) { | |
291 SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, origKey
, NULL)); | |
292 if (NULL == clampedTexture) { | |
293 clampedTexture.reset(this->createTexture(NULL, desc, origKey, srcData, r
owBytes)); | |
294 | |
295 if (NULL == clampedTexture) { | |
296 return NULL; | |
297 } | |
298 clampedTexture->cacheAccess().setContentKey(origKey); | |
299 } | |
300 | |
301 GrSurfaceDesc rtDesc = desc; | |
302 rtDesc.fFlags = rtDesc.fFlags | | |
303 kRenderTarget_GrSurfaceFlag | | |
304 kNoStencil_GrSurfaceFlag; | |
305 rtDesc.fWidth = GrNextPow2(desc.fWidth); | |
306 rtDesc.fHeight = GrNextPow2(desc.fHeight); | |
307 | |
308 GrTexture* texture = fGpu->createTexture(rtDesc, true, NULL, 0); | |
309 | |
310 if (texture) { | |
311 GrPipelineBuilder pipelineBuilder; | |
312 pipelineBuilder.setRenderTarget(texture->asRenderTarget()); | |
313 | |
314 // if filtering is not desired then we want to ensure all | |
315 // texels in the resampled image are copies of texels from | |
316 // the original. | |
317 GrTextureParams params(SkShader::kClamp_TileMode, | |
318 filter ? GrTextureParams::kBilerp_FilterMode : | |
319 GrTextureParams::kNone_FilterMode); | |
320 pipelineBuilder.addColorTextureProcessor(clampedTexture, SkMatrix::I(),
params); | |
321 | |
322 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | | |
323 GrDefaultGeoProcFactory::kLocalCoord_GPType; | |
324 SkAutoTUnref<const GrGeometryProcessor> gp( | |
325 GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE)); | |
326 | |
327 GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, gp->getVertexStrid
e(), 0); | |
328 SkASSERT(gp->getVertexStride() == 2 * sizeof(SkPoint)); | |
329 | |
330 if (arg.succeeded()) { | |
331 SkPoint* verts = (SkPoint*) arg.vertices(); | |
332 verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 *
sizeof(SkPoint)); | |
333 verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint)); | |
334 fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPri
mitiveType, 0, 4); | |
335 } else { | |
336 texture->unref(); | |
337 texture = NULL; | |
338 } | |
339 } else { | |
340 // TODO: Our CPU stretch doesn't filter. But we create separate | |
341 // stretched textures when the texture params is either filtered or | |
342 // not. Either implement filtered stretch blit on CPU or just create | |
343 // one when FBO case fails. | |
344 | |
345 rtDesc.fFlags = kNone_GrSurfaceFlags; | |
346 // no longer need to clamp at min RT size. | |
347 rtDesc.fWidth = GrNextPow2(desc.fWidth); | |
348 rtDesc.fHeight = GrNextPow2(desc.fHeight); | |
349 | |
350 // We shouldn't be resizing a compressed texture. | |
351 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); | |
352 | |
353 size_t bpp = GrBytesPerPixel(desc.fConfig); | |
354 GrAutoMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHe
ight); | |
355 stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight, | |
356 srcData, desc.fWidth, desc.fHeight, bpp); | |
357 | |
358 size_t stretchedRowBytes = rtDesc.fWidth * bpp; | |
359 | |
360 texture = fGpu->createTexture(rtDesc, true, stretchedPixels.get(), stret
chedRowBytes); | |
361 SkASSERT(texture); | |
362 } | |
363 | |
364 return texture; | |
365 } | |
366 | |
367 static GrContentKey::Domain ResizeDomain() { | |
368 static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); | |
369 return kDomain; | |
370 } | |
371 | |
372 GrTexture* GrContext::createTexture(const GrTextureParams* params, | |
373 const GrSurfaceDesc& desc, | |
374 const GrContentKey& origKey, | |
375 const void* srcData, | |
376 size_t rowBytes, | |
377 GrContentKey* outKey) { | |
378 GrTexture* texture; | |
379 uint32_t flags = get_texture_flags(fGpu, params, desc); | |
380 SkTCopyOnFirstWrite<GrContentKey> key(origKey); | |
381 if (flags) { | |
382 // We don't have a code path to resize compressed textures. | |
383 if (GrPixelConfigIsCompressed(desc.fConfig)) { | |
384 return NULL; | |
385 } | |
386 texture = this->createResizedTexture(desc, origKey, srcData, rowBytes, | |
387 SkToBool(flags & kBilerp_ResizeFlag
)); | |
388 | |
389 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); | |
390 builder[0] = flags; | |
391 | |
392 } else { | |
393 texture = fGpu->createTexture(desc, true, srcData, rowBytes); | |
394 } | |
395 | |
396 if (texture) { | |
397 if (texture->cacheAccess().setContentKey(*key)) { | |
398 if (outKey) { | |
399 *outKey = *key; | |
400 } | |
401 } else { | |
402 texture->unref(); | |
403 texture = NULL; | |
404 } | |
405 } | |
406 | |
407 return texture; | |
408 } | |
409 | |
410 GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc, | |
411 const GrContentKey& origKey, | |
412 const GrTextureParams* params) { | |
413 uint32_t flags = get_texture_flags(fGpu, params, desc); | |
414 SkTCopyOnFirstWrite<GrContentKey> key(origKey); | |
415 if (flags) { | |
416 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); | |
417 builder[0] = flags; | |
418 } | |
419 | |
420 GrGpuResource* resource = this->findAndRefCachedResource(*key); | |
421 if (resource) { | |
422 SkASSERT(static_cast<GrSurface*>(resource)->asTexture()); | |
423 return static_cast<GrSurface*>(resource)->asTexture(); | |
424 } | |
425 return NULL; | |
426 } | |
427 | |
428 bool GrContext::isTextureInCache(const GrSurfaceDesc& desc, | |
429 const GrContentKey& origKey, | |
430 const GrTextureParams* params) const { | |
431 uint32_t flags = get_texture_flags(fGpu, params, desc); | |
432 SkTCopyOnFirstWrite<GrContentKey> key(origKey); | |
433 if (flags) { | |
434 GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1
); | |
435 builder[0] = flags; | |
436 } | |
437 | |
438 return fResourceCache2->hasContentKey(*key); | |
439 } | 229 } |
440 | 230 |
441 GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
atch match, | 231 GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
atch match, |
442 bool calledDuringFlush) { | 232 bool calledDuringFlush) { |
443 // kNoStencil has no meaning if kRT isn't set. | 233 // kNoStencil has no meaning if kRT isn't set. |
444 SkASSERT((inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || | 234 SkASSERT((inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || |
445 !(inDesc.fFlags & kNoStencil_GrSurfaceFlag)); | 235 !(inDesc.fFlags & kNoStencil_GrSurfaceFlag)); |
446 | 236 |
447 // Make sure caller has checked for renderability if kRT is set. | 237 // Make sure caller has checked for renderability if kRT is set. |
448 SkASSERT(!(inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || | 238 SkASSERT(!(inDesc.fFlags & kRenderTarget_GrSurfaceFlag) || |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 // Flush the InOrderDrawBuffer to possibly free up some textures | 309 // Flush the InOrderDrawBuffer to possibly free up some textures |
520 context->fFlushToReduceCacheSize = true; | 310 context->fFlushToReduceCacheSize = true; |
521 } | 311 } |
522 | 312 |
523 GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc, | 313 GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc, |
524 void* srcData, | 314 void* srcData, |
525 size_t rowBytes) { | 315 size_t rowBytes) { |
526 return fGpu->createTexture(desc, false, srcData, rowBytes); | 316 return fGpu->createTexture(desc, false, srcData, rowBytes); |
527 } | 317 } |
528 | 318 |
529 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes
) const { | |
530 if (maxTextures) { | |
531 *maxTextures = fResourceCache2->getMaxResourceCount(); | |
532 } | |
533 if (maxTextureBytes) { | |
534 *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); | |
535 } | |
536 } | |
537 | |
538 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
{ | |
539 fResourceCache2->setLimits(maxTextures, maxTextureBytes); | |
540 } | |
541 | |
542 int GrContext::getMaxTextureSize() const { | 319 int GrContext::getMaxTextureSize() const { |
543 return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); | 320 return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); |
544 } | 321 } |
545 | 322 |
546 int GrContext::getMaxRenderTargetSize() const { | 323 int GrContext::getMaxRenderTargetSize() const { |
547 return fGpu->caps()->maxRenderTargetSize(); | 324 return fGpu->caps()->maxRenderTargetSize(); |
548 } | 325 } |
549 | 326 |
550 int GrContext::getMaxSampleCount() const { | 327 int GrContext::getMaxSampleCount() const { |
551 return fGpu->caps()->maxSampleCount(); | 328 return fGpu->caps()->maxSampleCount(); |
552 } | 329 } |
553 | 330 |
554 /////////////////////////////////////////////////////////////////////////////// | 331 /////////////////////////////////////////////////////////////////////////////// |
555 | 332 |
556 GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) { | 333 GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) { |
557 return fGpu->wrapBackendTexture(desc); | 334 return fGpu->wrapBackendTexture(desc); |
558 } | 335 } |
559 | 336 |
560 GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe
sc& desc) { | 337 GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe
sc& desc) { |
561 return fGpu->wrapBackendRenderTarget(desc); | 338 return fGpu->wrapBackendRenderTarget(desc); |
562 } | 339 } |
563 | 340 |
564 /////////////////////////////////////////////////////////////////////////////// | 341 /////////////////////////////////////////////////////////////////////////////// |
565 | 342 |
566 bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params, | 343 bool GrContext::supportsIndex8PixelConfig() const { |
567 int width, int height) const { | |
568 const GrDrawTargetCaps* caps = fGpu->caps(); | 344 const GrDrawTargetCaps* caps = fGpu->caps(); |
569 if (!caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { | 345 return caps->isConfigTexturable(kIndex_8_GrPixelConfig); |
570 return false; | |
571 } | |
572 | |
573 bool isPow2 = SkIsPow2(width) && SkIsPow2(height); | |
574 | |
575 if (!isPow2) { | |
576 bool tiled = params && params->isTiled(); | |
577 if (tiled && !caps->npotTextureTileSupport()) { | |
578 return false; | |
579 } | |
580 } | |
581 return true; | |
582 } | 346 } |
583 | 347 |
584 | 348 |
585 //////////////////////////////////////////////////////////////////////////////// | 349 //////////////////////////////////////////////////////////////////////////////// |
586 | 350 |
587 void GrContext::clear(const SkIRect* rect, | 351 void GrContext::clear(const SkIRect* rect, |
588 const GrColor color, | 352 const GrColor color, |
589 bool canIgnoreRect, | 353 bool canIgnoreRect, |
590 GrRenderTarget* renderTarget) { | 354 GrRenderTarget* renderTarget) { |
591 ASSERT_OWNED_RESOURCE(renderTarget); | 355 ASSERT_OWNED_RESOURCE(renderTarget); |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 } | 1524 } |
1761 GrConfigConversionEffect::PMConversion upmToPM = | 1525 GrConfigConversionEffect::PMConversion upmToPM = |
1762 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); | 1526 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); |
1763 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { | 1527 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { |
1764 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat
rix); | 1528 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat
rix); |
1765 } else { | 1529 } else { |
1766 return NULL; | 1530 return NULL; |
1767 } | 1531 } |
1768 } | 1532 } |
1769 | 1533 |
1770 void GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resou
rce) { | 1534 ////////////////////////////////////////////////////////////////////////////// |
1771 resource->cacheAccess().setContentKey(key); | 1535 |
| 1536 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes
) const { |
| 1537 if (maxTextures) { |
| 1538 *maxTextures = fResourceCache2->getMaxResourceCount(); |
| 1539 } |
| 1540 if (maxTextureBytes) { |
| 1541 *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); |
| 1542 } |
| 1543 } |
| 1544 |
| 1545 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes)
{ |
| 1546 fResourceCache2->setLimits(maxTextures, maxTextureBytes); |
| 1547 } |
| 1548 |
| 1549 bool GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resou
rce) { |
| 1550 ASSERT_OWNED_RESOURCE(resource); |
| 1551 if (!resource || resource->wasDestroyed()) { |
| 1552 return false; |
| 1553 } |
| 1554 return resource->cacheAccess().setContentKey(key); |
| 1555 } |
| 1556 |
| 1557 bool GrContext::isResourceInCache(const GrContentKey& key) const { |
| 1558 return fResourceCache2->hasContentKey(key); |
1772 } | 1559 } |
1773 | 1560 |
1774 GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { | 1561 GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { |
1775 return fResourceCache2->findAndRefContentResource(key); | 1562 return fResourceCache2->findAndRefContentResource(key); |
1776 } | 1563 } |
1777 | 1564 |
| 1565 ////////////////////////////////////////////////////////////////////////////// |
| 1566 |
1778 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { | 1567 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { |
1779 fGpu->addGpuTraceMarker(marker); | 1568 fGpu->addGpuTraceMarker(marker); |
1780 if (fDrawBuffer) { | 1569 if (fDrawBuffer) { |
1781 fDrawBuffer->addGpuTraceMarker(marker); | 1570 fDrawBuffer->addGpuTraceMarker(marker); |
1782 } | 1571 } |
1783 } | 1572 } |
1784 | 1573 |
1785 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 1574 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
1786 fGpu->removeGpuTraceMarker(marker); | 1575 fGpu->removeGpuTraceMarker(marker); |
1787 if (fDrawBuffer) { | 1576 if (fDrawBuffer) { |
1788 fDrawBuffer->removeGpuTraceMarker(marker); | 1577 fDrawBuffer->removeGpuTraceMarker(marker); |
1789 } | 1578 } |
1790 } | 1579 } |
1791 | 1580 |
1792 /////////////////////////////////////////////////////////////////////////////// | 1581 /////////////////////////////////////////////////////////////////////////////// |
1793 #if GR_CACHE_STATS | 1582 #if GR_CACHE_STATS |
1794 void GrContext::printCacheStats() const { | 1583 void GrContext::printCacheStats() const { |
1795 fResourceCache2->printStats(); | 1584 fResourceCache2->printStats(); |
1796 } | 1585 } |
1797 #endif | 1586 #endif |
1798 | 1587 |
1799 #if GR_GPU_STATS | 1588 #if GR_GPU_STATS |
1800 const GrContext::GPUStats* GrContext::gpuStats() const { | 1589 const GrContext::GPUStats* GrContext::gpuStats() const { |
1801 return fGpu->gpuStats(); | 1590 return fGpu->gpuStats(); |
1802 } | 1591 } |
1803 #endif | 1592 #endif |
1804 | 1593 |
OLD | NEW |