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

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: fix 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 GrContext::writeSurfacePixels(GrSurface* surface,
1248 int left, int top, int width, int height, 1249 int left, int top, int width, int height,
1249 GrPixelConfig config, const void* buffer, siz e_t rowBytes, 1250 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
1250 uint32_t flags) { 1251 uint32_t pixelOpsFlags) {
1251 ASSERT_OWNED_RESOURCE(texture);
1252 1252
1253 if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture , config)) { 1253 {
1254 if (texture->asRenderTarget()) { 1254 GrTexture* texture = NULL;
1255 return this->writeRenderTargetPixels(texture->asRenderTarget(), 1255 if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asT exture()) &&
1256 left, top, width, height, 1256 fGpu->canWriteTexturePixels(texture, srcConfig)) {
1257 config, buffer, rowBytes, flags ); 1257
1258 } else { 1258 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
1259 return false; 1259 surface->surfacePriv().hasPendingIO()) {
1260 this->flush();
1261 }
1262 return fGpu->writeTexturePixels(texture, left, top, width, height,
1263 srcConfig, buffer, rowBytes);
1264 // Don't need to check kFlushWrites_PixelOp here, we just did a dire ct write so the
1265 // upload is already flushed.
1260 } 1266 }
1261 } 1267 }
1262 1268
1263 if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingI O()) { 1269 // If we didn't do a direct texture write then we upload the pixels to a tex ture and draw.
1270 GrRenderTarget* renderTarget = surface->asRenderTarget();
1271 if (NULL == renderTarget) {
1272 return false;
1273 }
1274
1275 // We ignore the preferred config unless it is a R/B swap of the src config. In that case
1276 // we will upload the original src data to a scratch texture but we will spo of it as the swapped
1277 // config. This scratch will then have R and B swapped. We correct for this by swapping again
1278 // when drawing the scratch to the dst using a conversion effect.
1279 bool swapRAndB = false;
1280 GrPixelConfig writeConfig = srcConfig;
1281 if (GrPixelConfigSwapRAndB(srcConfig) ==
1282 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
1283 writeConfig = GrPixelConfigSwapRAndB(srcConfig);
1284 swapRAndB = true;
1285 }
1286
1287 GrTextureDesc desc;
1288 desc.fWidth = width;
1289 desc.fHeight = height;
1290 desc.fConfig = writeConfig;
1291 GrAutoScratchTexture ast(this, desc);
1292 GrTexture* texture = ast.texture();
1293 if (NULL == texture) {
1294 return false;
1295 }
1296
1297 SkAutoTUnref<const GrFragmentProcessor> fp;
1298 SkMatrix textureMatrix;
1299 textureMatrix.setIDiv(texture->width(), texture->height());
1300
1301 // allocate a tmp buffer and sw convert the pixels to premul
1302 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1303
1304 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
1305 if (!GrPixelConfigIs8888(srcConfig)) {
1306 return false;
1307 }
1308 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1309 // handle the unpremul step on the CPU if we couldn't create an effect t o do it.
1310 if (NULL == fp) {
robertphillips 2014/10/13 13:37:33 sw_convert_to_premul ? Not sure though it could be
bsalomon 2014/10/13 14:56:54 Done.
1311 SkSrcPixelInfo srcPI;
1312 if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
1313 return false;
1314 }
1315 srcPI.fAlphaType = kUnpremul_SkAlphaType;
1316 srcPI.fPixels = buffer;
1317 srcPI.fRowBytes = rowBytes;
1318
1319 tmpPixels.reset(width * height);
1320
1321 SkDstPixelInfo dstPI;
1322 dstPI.fColorType = srcPI.fColorType;
1323 dstPI.fAlphaType = kPremul_SkAlphaType;
1324 dstPI.fPixels = tmpPixels.get();
1325 dstPI.fRowBytes = 4 * width;
1326
1327 if (!srcPI.convertPixelsTo(&dstPI, width, height)) {
1328 return false;
1329 }
1330
1331 buffer = tmpPixels.get();
1332 rowBytes = 4 * width;
1333 }
1334 }
1335 if (NULL == fp) {
1336 fp.reset(GrConfigConversionEffect::Create(texture,
1337 swapRAndB,
1338 GrConfigConversionEffect::kNon e_PMConversion,
1339 textureMatrix));
1340 }
1341
1342 // Even if the client told us not to flush, we still flush here. The client may have known that
1343 // writes to the original surface caused no data hazards, but they can't kno w that the scratch
1344 // we just got is safe.
1345 if (texture->surfacePriv().hasPendingIO()) {
1264 this->flush(); 1346 this->flush();
1265 } 1347 }
1266 1348 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
1267 return fGpu->writeTexturePixels(texture, left, top, width, height, 1349 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; 1350 return false;
1309 } 1351 }
1352
1353 SkMatrix matrix;
1354 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1355
1356 // This function can be called in the midst of drawing another object (e.g., when uploading a
1357 // SW-rasterized clip while issuing a draw). So we push the current geometry state before
1358 // drawing a rect to the render target.
1359 // The bracket ensures we pop the stack if we wind up flushing below.
1360 {
1361 GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL);
1362 GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::k Reset_ASRInit,
1363 &matrix);
1364 GrDrawState* drawState = drawTarget->drawState();
1365 drawState->addColorProcessor(fp);
1366 drawState->setRenderTarget(renderTarget);
1367 drawState->disableState(GrDrawState::kClip_StateBit);
1368 drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToS calar(height)));
1369 }
1370
1371 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1372 this->flushSurfaceWrites(surface);
1373 }
1374
1375 return true;
1310 } 1376 }
1311 1377
1312 #include "SkConfig8888.h"
1313
1314 // toggles between RGBA and BGRA 1378 // toggles between RGBA and BGRA
1315 static SkColorType toggle_colortype32(SkColorType ct) { 1379 static SkColorType toggle_colortype32(SkColorType ct) {
1316 if (kRGBA_8888_SkColorType == ct) { 1380 if (kRGBA_8888_SkColorType == ct) {
1317 return kBGRA_8888_SkColorType; 1381 return kBGRA_8888_SkColorType;
1318 } else { 1382 } else {
1319 SkASSERT(kBGRA_8888_SkColorType == ct); 1383 SkASSERT(kBGRA_8888_SkColorType == ct);
1320 return kRGBA_8888_SkColorType; 1384 return kRGBA_8888_SkColorType;
1321 } 1385 }
1322 } 1386 }
1323 1387
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 return false; 1429 return false;
1366 } 1430 }
1367 1431
1368 // If the src is a texture and we would have to do conversions after read pi xels, we instead 1432 // 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 1433 // 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 1434 // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1371 // on the read back pixels. 1435 // on the read back pixels.
1372 GrTexture* src = target->asTexture(); 1436 GrTexture* src = target->asTexture();
1373 GrAutoScratchTexture ast; 1437 GrAutoScratchTexture ast;
1374 if (src && (swapRAndB || unpremul || flipY)) { 1438 if (src && (swapRAndB || unpremul || flipY)) {
1375 // Make the scratch a render target because we don't have a robust readT exturePixels as of 1439 // Make the scratch a render so we can read its pixels.
1376 // yet. It calls this function.
1377 GrTextureDesc desc; 1440 GrTextureDesc desc;
1378 desc.fFlags = kRenderTarget_GrTextureFlagBit; 1441 desc.fFlags = kRenderTarget_GrTextureFlagBit;
1379 desc.fWidth = width; 1442 desc.fWidth = width;
1380 desc.fHeight = height; 1443 desc.fHeight = height;
1381 desc.fConfig = readConfig; 1444 desc.fConfig = readConfig;
1382 desc.fOrigin = kTopLeft_GrSurfaceOrigin; 1445 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1383 1446
1384 // When a full read back is faster than a partial we could always make t he scratch exactly 1447 // 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 1448 // 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 1449 // 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) { 1564 if (NULL == target) {
1502 return; 1565 return;
1503 } 1566 }
1504 target->copySurface(dst, src, srcRect, dstPoint); 1567 target->copySurface(dst, src, srcRect, dstPoint);
1505 1568
1506 if (kFlushWrites_PixelOp & pixelOpsFlags) { 1569 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1507 this->flush(); 1570 this->flush();
1508 } 1571 }
1509 } 1572 }
1510 1573
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) { 1574 void GrContext::flushSurfaceWrites(GrSurface* surface) {
1650 if (surface->surfacePriv().hasPendingWrite()) { 1575 if (surface->surfacePriv().hasPendingWrite()) {
1651 this->flush(); 1576 this->flush();
1652 } 1577 }
1653 } 1578 }
1654 1579
1655 //////////////////////////////////////////////////////////////////////////////// 1580 ////////////////////////////////////////////////////////////////////////////////
1656 1581
1657 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, 1582 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
1658 BufferedDraw buffered, 1583 BufferedDraw buffered,
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 fResourceCache->printStats(); 1787 fResourceCache->printStats();
1863 } 1788 }
1864 #endif 1789 #endif
1865 1790
1866 #if GR_GPU_STATS 1791 #if GR_GPU_STATS
1867 const GrContext::GPUStats* GrContext::gpuStats() const { 1792 const GrContext::GPUStats* GrContext::gpuStats() const {
1868 return fGpu->gpuStats(); 1793 return fGpu->gpuStats();
1869 } 1794 }
1870 #endif 1795 #endif
1871 1796
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