| 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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 dstPI.fRowBytes = outRowBytes; | 322 dstPI.fRowBytes = outRowBytes; |
| 323 | 323 |
| 324 return srcPI.convertPixelsTo(&dstPI, width, height); | 324 return srcPI.convertPixelsTo(&dstPI, width, height); |
| 325 } | 325 } |
| 326 | 326 |
| 327 bool GrContext::writeSurfacePixels(GrSurface* surface, | 327 bool GrContext::writeSurfacePixels(GrSurface* surface, |
| 328 int left, int top, int width, int height, | 328 int left, int top, int width, int height, |
| 329 GrPixelConfig srcConfig, const void* buffer,
size_t rowBytes, | 329 GrPixelConfig srcConfig, const void* buffer,
size_t rowBytes, |
| 330 uint32_t pixelOpsFlags) { | 330 uint32_t pixelOpsFlags) { |
| 331 RETURN_FALSE_IF_ABANDONED | 331 RETURN_FALSE_IF_ABANDONED |
| 332 { | |
| 333 GrTexture* texture = NULL; | |
| 334 if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asT
exture()) && | |
| 335 fGpu->canWriteTexturePixels(texture, srcConfig) && | |
| 336 (!fCaps->useDrawInsteadOfPartialRenderTargetWrite() || !surface->asR
enderTarget() || | |
| 337 (width == texture->width() && height == texture->height()))) { | |
| 338 | |
| 339 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && | |
| 340 surface->surfacePriv().hasPendingIO()) { | |
| 341 this->flush(); | |
| 342 } | |
| 343 return fGpu->writeTexturePixels(texture, left, top, width, height, | |
| 344 srcConfig, buffer, rowBytes); | |
| 345 // Don't need to check kFlushWrites_PixelOp here, we just did a dire
ct write so the | |
| 346 // upload is already flushed. | |
| 347 } | |
| 348 } | |
| 349 | 332 |
| 350 // Trim the params here so that if we wind up making a temporary surface it
can be as small as | 333 // Trim the params here so that if we wind up making a temporary surface it
can be as small as |
| 351 // necessary. | 334 // necessary and because GrGpu::getWritePixelsInfo requires it. |
| 352 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height
(), | 335 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height
(), |
| 353 GrBytesPerPixel(srcConfig), &left
, &top, &width, | 336 GrBytesPerPixel(srcConfig), &left
, &top, &width, |
| 354 &height, &buffer, &rowBytes)) { | 337 &height, &buffer, &rowBytes)) { |
| 355 return false; | 338 return false; |
| 356 } | 339 } |
| 357 | 340 |
| 358 // If we didn't do a direct texture write then we upload the pixels to a tex
ture and draw. | 341 bool applyPremulToSrc = false; |
| 359 GrRenderTarget* renderTarget = surface->asRenderTarget(); | |
| 360 if (!renderTarget) { | |
| 361 return false; | |
| 362 } | |
| 363 | |
| 364 // We ignore the preferred config unless it is a R/B swap of the src config.
In that case | |
| 365 // we will upload the original src data to a scratch texture but we will spo
of it as the swapped | |
| 366 // config. This scratch will then have R and B swapped. We correct for this
by swapping again | |
| 367 // when drawing the scratch to the dst using a conversion effect. | |
| 368 bool swapRAndB = false; | |
| 369 GrPixelConfig writeConfig = srcConfig; | |
| 370 if (GrPixelConfigSwapRAndB(srcConfig) == | |
| 371 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) { | |
| 372 writeConfig = GrPixelConfigSwapRAndB(srcConfig); | |
| 373 swapRAndB = true; | |
| 374 } | |
| 375 | |
| 376 GrSurfaceDesc desc; | |
| 377 desc.fWidth = width; | |
| 378 desc.fHeight = height; | |
| 379 desc.fConfig = writeConfig; | |
| 380 SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(d
esc, | |
| 381 GrTextureProvider::kApprox_ScratchTexMatch)); | |
| 382 if (!texture) { | |
| 383 return false; | |
| 384 } | |
| 385 | |
| 386 SkAutoTUnref<const GrFragmentProcessor> fp; | |
| 387 SkMatrix textureMatrix; | |
| 388 textureMatrix.setIDiv(texture->width(), texture->height()); | |
| 389 | |
| 390 // allocate a tmp buffer and sw convert the pixels to premul | |
| 391 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); | |
| 392 | |
| 393 GrPaint paint; | |
| 394 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { | 342 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { |
| 395 if (!GrPixelConfigIs8888(srcConfig)) { | 343 if (!GrPixelConfigIs8888(srcConfig)) { |
| 396 return false; | 344 return false; |
| 397 } | 345 } |
| 398 fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), text
ure, swapRAndB, | 346 applyPremulToSrc = true; |
| 399 textureMatrix)); | 347 } |
| 400 // handle the unpremul step on the CPU if we couldn't create an effect t
o do it. | 348 GrGpu::DrawPreference drawPreference = applyPremulToSrc ? |
| 401 if (!fp) { | 349 GrGpu::kCallerPrefersDraw_DrawPrefer
ence : |
| 350 GrGpu::kNoDraw_DrawPreference; |
| 351 GrGpu::WritePixelTempDrawInfo tempDrawInfo; |
| 352 if (!fGpu->getWritePixelsInfo(surface, width, height, rowBytes, srcConfig, &
drawPreference, |
| 353 &tempDrawInfo)) { |
| 354 return false; |
| 355 } |
| 356 |
| 357 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().has
PendingIO()) { |
| 358 this->flush(); |
| 359 } |
| 360 |
| 361 SkAutoTUnref<GrTexture> tempTexture; |
| 362 if (GrGpu::kNoDraw_DrawPreference != drawPreference) { |
| 363 tempTexture.reset(this->textureProvider()->refScratchTexture( |
| 364 tempDrawInfo.fTempSurfaceDesc, GrTextureProvider::kApprox_ScratchTex
Match)); |
| 365 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference
) { |
| 366 return false; |
| 367 } |
| 368 } |
| 369 |
| 370 // temp buffer for doing sw premul conversion, if needed. |
| 371 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); |
| 372 if (tempTexture) { |
| 373 SkAutoTUnref<const GrFragmentProcessor> fp; |
| 374 SkMatrix textureMatrix; |
| 375 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height()); |
| 376 GrPaint paint; |
| 377 if (applyPremulToSrc) { |
| 378 fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(),
tempTexture, |
| 379 tempDrawInfo.fSwapRAndB, textureM
atrix)); |
| 380 // If premultiplying was the only reason for the draw, fall back to
a straight write. |
| 381 if (!fp) { |
| 382 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference)
{ |
| 383 tempTexture.reset(NULL); |
| 384 } |
| 385 } else { |
| 386 applyPremulToSrc = false; |
| 387 } |
| 388 } |
| 389 if (tempTexture) { |
| 390 if (!fp) { |
| 391 fp.reset(GrConfigConversionEffect::Create( |
| 392 paint.getProcessorDataManager(), tempTexture, tempDrawInfo.f
SwapRAndB, |
| 393 GrConfigConversionEffect::kNone_PMConversion, textureMatrix)
); |
| 394 if (!fp) { |
| 395 return false; |
| 396 } |
| 397 } |
| 398 GrRenderTarget* renderTarget = surface->asRenderTarget(); |
| 399 SkASSERT(renderTarget); |
| 400 if (tempTexture->surfacePriv().hasPendingIO()) { |
| 401 this->flush(); |
| 402 } |
| 403 if (applyPremulToSrc) { |
| 404 size_t tmpRowBytes = 4 * width; |
| 405 tmpPixels.reset(width * height); |
| 406 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, bu
ffer, tmpRowBytes, |
| 407 tmpPixels.get())) { |
| 408 return false; |
| 409 } |
| 410 rowBytes = tmpRowBytes; |
| 411 buffer = tmpPixels.get(); |
| 412 applyPremulToSrc = false; |
| 413 } |
| 414 if (!fGpu->writeTexturePixels(tempTexture, 0, 0, width, height, |
| 415 tempDrawInfo.fTempSurfaceDesc.fConfig,
buffer, |
| 416 rowBytes)) { |
| 417 return false; |
| 418 } |
| 419 SkMatrix matrix; |
| 420 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); |
| 421 GrDrawContext* drawContext = this->drawContext(); |
| 422 if (!drawContext) { |
| 423 return false; |
| 424 } |
| 425 paint.addColorProcessor(fp); |
| 426 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(hei
ght)); |
| 427 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matri
x, rect, NULL); |
| 428 |
| 429 if (kFlushWrites_PixelOp & pixelOpsFlags) { |
| 430 this->flushSurfaceWrites(surface); |
| 431 } |
| 432 } |
| 433 } |
| 434 if (!tempTexture) { |
| 435 SkASSERT(surface->asTexture()); |
| 436 if (applyPremulToSrc) { |
| 402 size_t tmpRowBytes = 4 * width; | 437 size_t tmpRowBytes = 4 * width; |
| 403 tmpPixels.reset(width * height); | 438 tmpPixels.reset(width * height); |
| 404 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer
, tmpRowBytes, | 439 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer
, tmpRowBytes, |
| 405 tmpPixels.get())) { | 440 tmpPixels.get())) { |
| 406 return false; | 441 return false; |
| 407 } | 442 } |
| 408 rowBytes = tmpRowBytes; | 443 rowBytes = tmpRowBytes; |
| 409 buffer = tmpPixels.get(); | 444 buffer = tmpPixels.get(); |
| 445 applyPremulToSrc = false; |
| 410 } | 446 } |
| 447 return fGpu->writeTexturePixels(surface->asTexture(), left, top, width,
height, srcConfig, |
| 448 buffer, rowBytes); |
| 411 } | 449 } |
| 412 | |
| 413 if (!fp) { | |
| 414 fp.reset(GrConfigConversionEffect::Create(paint.getProcessorDataManager(
), | |
| 415 texture, | |
| 416 swapRAndB, | |
| 417 GrConfigConversionEffect::kNon
e_PMConversion, | |
| 418 textureMatrix)); | |
| 419 } | |
| 420 | |
| 421 // Even if the client told us not to flush, we still flush here. The client
may have known that | |
| 422 // writes to the original surface caused no data hazards, but they can't kno
w that the scratch | |
| 423 // we just got is safe. | |
| 424 if (texture->surfacePriv().hasPendingIO()) { | |
| 425 this->flush(); | |
| 426 } | |
| 427 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height, | |
| 428 writeConfig, buffer, rowBytes)) { | |
| 429 return false; | |
| 430 } | |
| 431 | |
| 432 SkMatrix matrix; | |
| 433 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); | |
| 434 | |
| 435 GrDrawContext* drawContext = this->drawContext(); | |
| 436 if (!drawContext) { | |
| 437 return false; | |
| 438 } | |
| 439 | |
| 440 paint.addColorProcessor(fp); | |
| 441 | |
| 442 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); | |
| 443 | |
| 444 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect,
NULL); | |
| 445 | |
| 446 if (kFlushWrites_PixelOp & pixelOpsFlags) { | |
| 447 this->flushSurfaceWrites(surface); | |
| 448 } | |
| 449 | |
| 450 return true; | 450 return true; |
| 451 } | 451 } |
| 452 | 452 |
| 453 bool GrContext::readSurfacePixels(GrSurface* src, | 453 bool GrContext::readSurfacePixels(GrSurface* src, |
| 454 int left, int top, int width, int height, | 454 int left, int top, int width, int height, |
| 455 GrPixelConfig dstConfig, void* buffer, size_t
rowBytes, | 455 GrPixelConfig dstConfig, void* buffer, size_t
rowBytes, |
| 456 uint32_t flags) { | 456 uint32_t flags) { |
| 457 RETURN_FALSE_IF_ABANDONED | 457 RETURN_FALSE_IF_ABANDONED |
| 458 ASSERT_OWNED_RESOURCE(src); | 458 ASSERT_OWNED_RESOURCE(src); |
| 459 SkASSERT(src); | 459 SkASSERT(src); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 ////////////////////////////////////////////////////////////////////////////// | 736 ////////////////////////////////////////////////////////////////////////////// |
| 737 | 737 |
| 738 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { | 738 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { |
| 739 fGpu->addGpuTraceMarker(marker); | 739 fGpu->addGpuTraceMarker(marker); |
| 740 } | 740 } |
| 741 | 741 |
| 742 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 742 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
| 743 fGpu->removeGpuTraceMarker(marker); | 743 fGpu->removeGpuTraceMarker(marker); |
| 744 } | 744 } |
| 745 | 745 |
| OLD | NEW |