Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/gpu/GrContext.cpp

Issue 648863002: Devirtualize read/write pixels on surface. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: simplify return Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrAtlas.cpp ('k') | src/gpu/GrDistanceFieldTextContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 17 matching lines...) Expand all
28 #include "GrSoftwarePathRenderer.h" 28 #include "GrSoftwarePathRenderer.h"
29 #include "GrStencilBuffer.h" 29 #include "GrStencilBuffer.h"
30 #include "GrStencilAndCoverTextContext.h" 30 #include "GrStencilAndCoverTextContext.h"
31 #include "GrStrokeInfo.h" 31 #include "GrStrokeInfo.h"
32 #include "GrSurfacePriv.h" 32 #include "GrSurfacePriv.h"
33 #include "GrTextStrike.h" 33 #include "GrTextStrike.h"
34 #include "GrTexturePriv.h" 34 #include "GrTexturePriv.h"
35 #include "GrTraceMarker.h" 35 #include "GrTraceMarker.h"
36 #include "GrTracing.h" 36 #include "GrTracing.h"
37 #include "SkDashPathPriv.h" 37 #include "SkDashPathPriv.h"
38 #include "SkConfig8888.h"
38 #include "SkGr.h" 39 #include "SkGr.h"
39 #include "SkRTConf.h" 40 #include "SkRTConf.h"
40 #include "SkRRect.h" 41 #include "SkRRect.h"
41 #include "SkStrokeRec.h" 42 #include "SkStrokeRec.h"
42 #include "SkTLazy.h" 43 #include "SkTLazy.h"
43 #include "SkTLS.h" 44 #include "SkTLS.h"
44 #include "SkTraceEvent.h" 45 #include "SkTraceEvent.h"
45 46
46 // It can be useful to set this to false to test whether a bug is caused by usin g the 47 // It can be useful to set this to false to test whether a bug is caused by usin g the
47 // InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffe r, or to make 48 // InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffe r, or to make
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 1238
1238 if (kDiscard_FlushBit & flagsBitfield) { 1239 if (kDiscard_FlushBit & flagsBitfield) {
1239 fDrawBuffer->reset(); 1240 fDrawBuffer->reset();
1240 } else { 1241 } else {
1241 fDrawBuffer->flush(); 1242 fDrawBuffer->flush();
1242 } 1243 }
1243 fResourceCache->purgeAsNeeded(); 1244 fResourceCache->purgeAsNeeded();
1244 fFlushToReduceCacheSize = false; 1245 fFlushToReduceCacheSize = false;
1245 } 1246 }
1246 1247
1247 bool GrContext::writeTexturePixels(GrTexture* texture, 1248 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
1249 const void* inPixels, size_t outRowBytes, void* outPix els) {
1250 SkSrcPixelInfo srcPI;
1251 if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
1252 return false;
1253 }
1254 srcPI.fAlphaType = kUnpremul_SkAlphaType;
1255 srcPI.fPixels = inPixels;
1256 srcPI.fRowBytes = inRowBytes;
1257
1258 SkDstPixelInfo dstPI;
1259 dstPI.fColorType = srcPI.fColorType;
1260 dstPI.fAlphaType = kPremul_SkAlphaType;
1261 dstPI.fPixels = outPixels;
1262 dstPI.fRowBytes = outRowBytes;
1263
1264 return srcPI.convertPixelsTo(&dstPI, width, height);
1265 }
1266
1267 bool GrContext::writeSurfacePixels(GrSurface* surface,
1248 int left, int top, int width, int height, 1268 int left, int top, int width, int height,
1249 GrPixelConfig config, const void* buffer, siz e_t rowBytes, 1269 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
1250 uint32_t flags) { 1270 uint32_t pixelOpsFlags) {
1251 ASSERT_OWNED_RESOURCE(texture);
1252 1271
1253 if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture , config)) { 1272 {
1254 if (texture->asRenderTarget()) { 1273 GrTexture* texture = NULL;
1255 return this->writeRenderTargetPixels(texture->asRenderTarget(), 1274 if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asT exture()) &&
1256 left, top, width, height, 1275 fGpu->canWriteTexturePixels(texture, srcConfig)) {
1257 config, buffer, rowBytes, flags ); 1276
1258 } else { 1277 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
1259 return false; 1278 surface->surfacePriv().hasPendingIO()) {
1279 this->flush();
1280 }
1281 return fGpu->writeTexturePixels(texture, left, top, width, height,
1282 srcConfig, buffer, rowBytes);
1283 // Don't need to check kFlushWrites_PixelOp here, we just did a dire ct write so the
1284 // upload is already flushed.
1260 } 1285 }
1261 } 1286 }
1262 1287
1263 if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingI O()) { 1288 // If we didn't do a direct texture write then we upload the pixels to a tex ture and draw.
1289 GrRenderTarget* renderTarget = surface->asRenderTarget();
1290 if (NULL == renderTarget) {
1291 return false;
1292 }
1293
1294 // We ignore the preferred config unless it is a R/B swap of the src config. In that case
1295 // we will upload the original src data to a scratch texture but we will spo of it as the swapped
1296 // config. This scratch will then have R and B swapped. We correct for this by swapping again
1297 // when drawing the scratch to the dst using a conversion effect.
1298 bool swapRAndB = false;
1299 GrPixelConfig writeConfig = srcConfig;
1300 if (GrPixelConfigSwapRAndB(srcConfig) ==
1301 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
1302 writeConfig = GrPixelConfigSwapRAndB(srcConfig);
1303 swapRAndB = true;
1304 }
1305
1306 GrTextureDesc desc;
1307 desc.fWidth = width;
1308 desc.fHeight = height;
1309 desc.fConfig = writeConfig;
1310 GrAutoScratchTexture ast(this, desc);
1311 GrTexture* texture = ast.texture();
1312 if (NULL == texture) {
1313 return false;
1314 }
1315
1316 SkAutoTUnref<const GrFragmentProcessor> fp;
1317 SkMatrix textureMatrix;
1318 textureMatrix.setIDiv(texture->width(), texture->height());
1319
1320 // allocate a tmp buffer and sw convert the pixels to premul
1321 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1322
1323 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
1324 if (!GrPixelConfigIs8888(srcConfig)) {
1325 return false;
1326 }
1327 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1328 // handle the unpremul step on the CPU if we couldn't create an effect t o do it.
1329 if (NULL == fp) {
1330 size_t tmpRowBytes = 4 * width;
1331 tmpPixels.reset(width * height);
1332 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer , tmpRowBytes,
1333 tmpPixels.get())) {
1334 return false;
1335 }
1336 rowBytes = tmpRowBytes;
1337 buffer = tmpPixels.get();
1338 }
1339 }
1340 if (NULL == fp) {
1341 fp.reset(GrConfigConversionEffect::Create(texture,
1342 swapRAndB,
1343 GrConfigConversionEffect::kNon e_PMConversion,
1344 textureMatrix));
1345 }
1346
1347 // Even if the client told us not to flush, we still flush here. The client may have known that
1348 // writes to the original surface caused no data hazards, but they can't kno w that the scratch
1349 // we just got is safe.
1350 if (texture->surfacePriv().hasPendingIO()) {
1264 this->flush(); 1351 this->flush();
1265 } 1352 }
1266 1353 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
1267 return fGpu->writeTexturePixels(texture, left, top, width, height, 1354 writeConfig, buffer, rowBytes)) {
1268 config, buffer, rowBytes);
1269
1270 // No need to check the kFlushWrites flag here since we issued the write dir ectly to fGpu.
1271 }
1272
1273 bool GrContext::readTexturePixels(GrTexture* texture,
1274 int left, int top, int width, int height,
1275 GrPixelConfig config, void* buffer, size_t row Bytes,
1276 uint32_t flags) {
1277 ASSERT_OWNED_RESOURCE(texture);
1278
1279 GrRenderTarget* target = texture->asRenderTarget();
1280 if (target) {
1281 return this->readRenderTargetPixels(target,
1282 left, top, width, height,
1283 config, buffer, rowBytes,
1284 flags);
1285 } else {
1286 // TODO: make this more efficient for cases where we're reading the enti re
1287 // texture, i.e., use GetTexImage() instead
1288
1289 // create scratch rendertarget and read from that
1290 GrAutoScratchTexture ast;
1291 GrTextureDesc desc;
1292 desc.fFlags = kRenderTarget_GrTextureFlagBit;
1293 desc.fWidth = width;
1294 desc.fHeight = height;
1295 desc.fConfig = config;
1296 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1297 ast.set(this, desc, kExact_ScratchTexMatch);
1298 GrTexture* dst = ast.texture();
1299 if (dst && (target = dst->asRenderTarget())) {
1300 this->copySurface(target, texture, SkIRect::MakeXYWH(top, left, widt h, height),
1301 SkIPoint::Make(0,0));
1302 return this->readRenderTargetPixels(target,
1303 left, top, width, height,
1304 config, buffer, rowBytes,
1305 flags);
1306 }
1307
1308 return false; 1355 return false;
1309 } 1356 }
1357
1358 SkMatrix matrix;
1359 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1360
1361 // This function can be called in the midst of drawing another object (e.g., when uploading a
1362 // SW-rasterized clip while issuing a draw). So we push the current geometry state before
1363 // drawing a rect to the render target.
1364 // The bracket ensures we pop the stack if we wind up flushing below.
1365 {
1366 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL);
1367 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::k Reset_ASRInit,
1368 &matrix);
1369 GrDrawState* drawState = drawTarget->drawState();
1370 drawState->addColorProcessor(fp);
1371 drawState->setRenderTarget(renderTarget);
1372 drawState->disableState(GrDrawState::kClip_StateBit);
1373 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToS calar(height)));
1374 }
1375
1376 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1377 this->flushSurfaceWrites(surface);
1378 }
1379
1380 return true;
1310 } 1381 }
1311 1382
1312 #include "SkConfig8888.h"
1313
1314 // toggles between RGBA and BGRA 1383 // toggles between RGBA and BGRA
1315 static SkColorType toggle_colortype32(SkColorType ct) { 1384 static SkColorType toggle_colortype32(SkColorType ct) {
1316 if (kRGBA_8888_SkColorType == ct) { 1385 if (kRGBA_8888_SkColorType == ct) {
1317 return kBGRA_8888_SkColorType; 1386 return kBGRA_8888_SkColorType;
1318 } else { 1387 } else {
1319 SkASSERT(kBGRA_8888_SkColorType == ct); 1388 SkASSERT(kBGRA_8888_SkColorType == ct);
1320 return kRGBA_8888_SkColorType; 1389 return kRGBA_8888_SkColorType;
1321 } 1390 }
1322 } 1391 }
1323 1392
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 return false; 1434 return false;
1366 } 1435 }
1367 1436
1368 // If the src is a texture and we would have to do conversions after read pi xels, we instead 1437 // If the src is a texture and we would have to do conversions after read pi xels, we instead
1369 // do the conversions by drawing the src to a scratch texture. If we handle any of the 1438 // do the conversions by drawing the src to a scratch texture. If we handle any of the
1370 // conversions in the draw we set the corresponding bool to false so that we don't reapply it 1439 // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1371 // on the read back pixels. 1440 // on the read back pixels.
1372 GrTexture* src = target->asTexture(); 1441 GrTexture* src = target->asTexture();
1373 GrAutoScratchTexture ast; 1442 GrAutoScratchTexture ast;
1374 if (src && (swapRAndB || unpremul || flipY)) { 1443 if (src && (swapRAndB || unpremul || flipY)) {
1375 // Make the scratch a render target because we don't have a robust readT exturePixels as of 1444 // Make the scratch a render so we can read its pixels.
1376 // yet. It calls this function.
1377 GrTextureDesc desc; 1445 GrTextureDesc desc;
1378 desc.fFlags = kRenderTarget_GrTextureFlagBit; 1446 desc.fFlags = kRenderTarget_GrTextureFlagBit;
1379 desc.fWidth = width; 1447 desc.fWidth = width;
1380 desc.fHeight = height; 1448 desc.fHeight = height;
1381 desc.fConfig = readConfig; 1449 desc.fConfig = readConfig;
1382 desc.fOrigin = kTopLeft_GrSurfaceOrigin; 1450 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1383 1451
1384 // When a full read back is faster than a partial we could always make t he scratch exactly 1452 // When a full read back is faster than a partial we could always make t he scratch exactly
1385 // match the passed rect. However, if we see many different size rectang les we will trash 1453 // match the passed rect. However, if we see many different size rectang les we will trash
1386 // our texture cache and pay the cost of creating and destroying many te xtures. So, we only 1454 // our texture cache and pay the cost of creating and destroying many te xtures. So, we only
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 if (NULL == target) { 1569 if (NULL == target) {
1502 return; 1570 return;
1503 } 1571 }
1504 target->copySurface(dst, src, srcRect, dstPoint); 1572 target->copySurface(dst, src, srcRect, dstPoint);
1505 1573
1506 if (kFlushWrites_PixelOp & pixelOpsFlags) { 1574 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1507 this->flush(); 1575 this->flush();
1508 } 1576 }
1509 } 1577 }
1510 1578
1511 bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget,
1512 int left, int top, int width, int height ,
1513 GrPixelConfig srcConfig,
1514 const void* buffer,
1515 size_t rowBytes,
1516 uint32_t pixelOpsFlags) {
1517 ASSERT_OWNED_RESOURCE(renderTarget);
1518
1519 if (NULL == renderTarget) {
1520 renderTarget = fRenderTarget.get();
1521 if (NULL == renderTarget) {
1522 return false;
1523 }
1524 }
1525
1526 // TODO: when underlying api has a direct way to do this we should use it (e .g. glDrawPixels on
1527 // desktop GL).
1528
1529 // We will always call some form of writeTexturePixels and we will pass our flags on to it.
1530 // Thus, we don't perform a flush here since that call will do it (if the kN oFlush flag isn't
1531 // set.)
1532
1533 // If the RT is also a texture and we don't have to premultiply then take th e texture path.
1534 // We expect to be at least as fast or faster since it doesn't use an interm ediate texture as
1535 // we do below.
1536
1537 #if !defined(SK_BUILD_FOR_MAC)
1538 // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
1539 // attached to an FBO. The FBO still sees the old image. TODO: determine wha t OS versions and/or
1540 // HW is affected.
1541 if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & pixelOpsFlags) & &
1542 fGpu->canWriteTexturePixels(renderTarget->asTexture(), srcConfig)) {
1543 return this->writeTexturePixels(renderTarget->asTexture(),
1544 left, top, width, height,
1545 srcConfig, buffer, rowBytes, pixelOpsFla gs);
1546 }
1547 #endif
1548
1549 // We ignore the preferred config unless it is a R/B swap of the src config. In that case
1550 // we will upload the original src data to a scratch texture but we will spo of it as the swapped
1551 // config. This scratch will then have R and B swapped. We correct for this by swapping again
1552 // when drawing the scratch to the dst using a conversion effect.
1553 bool swapRAndB = false;
1554 GrPixelConfig writeConfig = srcConfig;
1555 if (GrPixelConfigSwapRAndB(srcConfig) ==
1556 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
1557 writeConfig = GrPixelConfigSwapRAndB(srcConfig);
1558 swapRAndB = true;
1559 }
1560
1561 GrTextureDesc desc;
1562 desc.fWidth = width;
1563 desc.fHeight = height;
1564 desc.fConfig = writeConfig;
1565 GrAutoScratchTexture ast(this, desc);
1566 GrTexture* texture = ast.texture();
1567 if (NULL == texture) {
1568 return false;
1569 }
1570
1571 SkAutoTUnref<const GrFragmentProcessor> fp;
1572 SkMatrix textureMatrix;
1573 textureMatrix.setIDiv(texture->width(), texture->height());
1574
1575 // allocate a tmp buffer and sw convert the pixels to premul
1576 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1577
1578 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
1579 if (!GrPixelConfigIs8888(srcConfig)) {
1580 return false;
1581 }
1582 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1583 // handle the unpremul step on the CPU if we couldn't create an effect t o do it.
1584 if (NULL == fp) {
1585 SkSrcPixelInfo srcPI;
1586 if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
1587 return false;
1588 }
1589 srcPI.fAlphaType = kUnpremul_SkAlphaType;
1590 srcPI.fPixels = buffer;
1591 srcPI.fRowBytes = rowBytes;
1592
1593 tmpPixels.reset(width * height);
1594
1595 SkDstPixelInfo dstPI;
1596 dstPI.fColorType = srcPI.fColorType;
1597 dstPI.fAlphaType = kPremul_SkAlphaType;
1598 dstPI.fPixels = tmpPixels.get();
1599 dstPI.fRowBytes = 4 * width;
1600
1601 if (!srcPI.convertPixelsTo(&dstPI, width, height)) {
1602 return false;
1603 }
1604
1605 buffer = tmpPixels.get();
1606 rowBytes = 4 * width;
1607 }
1608 }
1609 if (NULL == fp) {
1610 fp.reset(GrConfigConversionEffect::Create(texture,
1611 swapRAndB,
1612 GrConfigConversionEffect::kNon e_PMConversion,
1613 textureMatrix));
1614 }
1615
1616 if (!this->writeTexturePixels(texture,
1617 0, 0, width, height,
1618 writeConfig, buffer, rowBytes,
1619 pixelOpsFlags & ~kUnpremul_PixelOpsFlag)) {
1620 return false;
1621 }
1622
1623 SkMatrix matrix;
1624 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1625
1626
1627 // This function can be called in the midst of drawing another object (e.g., when uploading a
1628 // SW-rasterized clip while issuing a draw). So we push the current geometry state before
1629 // drawing a rect to the render target.
1630 // The bracket ensures we pop the stack if we wind up flushing below.
1631 {
1632 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL);
1633 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::k Reset_ASRInit,
1634 &matrix);
1635 GrDrawState* drawState = drawTarget->drawState();
1636 drawState->addColorProcessor(fp);
1637 drawState->setRenderTarget(renderTarget);
1638 drawState->disableState(GrDrawState::kClip_StateBit);
1639 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToS calar(height)));
1640 }
1641
1642 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1643 this->flush();
1644 }
1645
1646 return true;
1647 }
1648
1649 void GrContext::flushSurfaceWrites(GrSurface* surface) { 1579 void GrContext::flushSurfaceWrites(GrSurface* surface) {
1650 if (surface->surfacePriv().hasPendingWrite()) { 1580 if (surface->surfacePriv().hasPendingWrite()) {
1651 this->flush(); 1581 this->flush();
1652 } 1582 }
1653 } 1583 }
1654 1584
1655 //////////////////////////////////////////////////////////////////////////////// 1585 ////////////////////////////////////////////////////////////////////////////////
1656 1586
1657 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, 1587 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
1658 BufferedDraw buffered, 1588 BufferedDraw buffered,
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 fResourceCache->printStats(); 1792 fResourceCache->printStats();
1863 } 1793 }
1864 #endif 1794 #endif
1865 1795
1866 #if GR_GPU_STATS 1796 #if GR_GPU_STATS
1867 const GrContext::GPUStats* GrContext::gpuStats() const { 1797 const GrContext::GPUStats* GrContext::gpuStats() const {
1868 return fGpu->gpuStats(); 1798 return fGpu->gpuStats();
1869 } 1799 }
1870 #endif 1800 #endif
1871 1801
OLDNEW
« no previous file with comments | « src/gpu/GrAtlas.cpp ('k') | src/gpu/GrDistanceFieldTextContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698