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 |