Devirtualize read/write pixels on surface.

Consolidate read/write funcs in context.

Remove support for reading pixels from a surface that's not a target. It's currently broken and neither used nor tested.

Review URL: https://codereview.chromium.org/648863002
This commit is contained in:
bsalomon 2014-10-13 12:32:55 -07:00 committed by Commit bot
parent 335a0ae19c
commit 81beccc4fb
13 changed files with 192 additions and 374 deletions

View File

@ -630,53 +630,8 @@ public:
uint32_t pixelOpsFlags = 0);
/**
* Copy the src pixels [buffer, row bytes, pixel config] into a render target at the specified
* rectangle.
* @param target the render target to write into. NULL means the current render target.
* @param left left edge of the rectangle to write (inclusive)
* @param top top edge of the rectangle to write (inclusive)
* @param width width of rectangle to write in pixels.
* @param height height of rectangle to write in pixels.
* @param config the pixel config of the source buffer
* @param buffer memory to read the rectangle from.
* @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
* packed.
* @param pixelOpsFlags see PixelOpsFlags enum above.
*
* @return true if the write succeeded, false if not. The write can fail because of an
* unsupported combination of target and pixel configs.
*/
bool writeRenderTargetPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, const void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0);
/**
* Reads a rectangle of pixels from a texture.
* @param texture the texture to read from.
* @param left left edge of the rectangle to read (inclusive)
* @param top top edge of the rectangle to read (inclusive)
* @param width width of rectangle to read in pixels.
* @param height height of rectangle to read in pixels.
* @param config the pixel config of the destination buffer
* @param buffer memory to read the rectangle into.
* @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
* packed.
* @param pixelOpsFlags see PixelOpsFlags enum above.
*
* @return true if the read succeeded, false if not. The read can fail because of an unsupported
* pixel config.
*/
bool readTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0);
/**
* Writes a rectangle of pixels to a texture.
* @param texture the render target to read from.
* Writes a rectangle of pixels to a surface.
* @param surface the surface to write to.
* @param left left edge of the rectangle to write (inclusive)
* @param top top edge of the rectangle to write (inclusive)
* @param width width of rectangle to write in pixels.
@ -687,9 +642,9 @@ public:
* means rows are tightly packed.
* @param pixelOpsFlags see PixelOpsFlags enum above.
* @return true if the write succeeded, false if not. The write can fail because of an
* unsupported combination of texture and pixel configs.
* unsupported combination of surface and src configs.
*/
bool writeTexturePixels(GrTexture* texture,
bool writeSurfacePixels(GrSurface* surface,
int left, int top, int width, int height,
GrPixelConfig config, const void* buffer,
size_t rowBytes,

View File

@ -43,18 +43,6 @@ public:
return this;
}
virtual bool readPixels(int left, int top, int width, int height,
GrPixelConfig config,
void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
virtual void writePixels(int left, int top, int width, int height,
GrPixelConfig config,
const void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
// GrRenderTarget
/**
* If this RT is multisampled, this is the multisample buffer

View File

@ -87,11 +87,11 @@ public:
* @return true if the read succeeded, false if not. The read can fail because of an unsupported
* pixel config.
*/
virtual bool readPixels(int left, int top, int width, int height,
GrPixelConfig config,
void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) = 0;
bool readPixels(int left, int top, int width, int height,
GrPixelConfig config,
void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0);
/**
* Copy the src pixels [buffer, rowbytes, pixelconfig] into the surface at the specified
@ -106,11 +106,11 @@ public:
* packed.
* @param pixelOpsFlags See the GrContext::PixelOpsFlags enum.
*/
virtual void writePixels(int left, int top, int width, int height,
GrPixelConfig config,
const void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) = 0;
bool writePixels(int left, int top, int width, int height,
GrPixelConfig config,
const void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0);
/**
* After this returns any pending writes to the surface will be issued to the backend 3D API.

View File

@ -25,19 +25,6 @@ public:
*/
virtual size_t gpuMemorySize() const SK_OVERRIDE;
// GrSurface overrides
virtual bool readPixels(int left, int top, int width, int height,
GrPixelConfig config,
void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
virtual void writePixels(int left, int top, int width, int height,
GrPixelConfig config,
const void* buffer,
size_t rowBytes = 0,
uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
virtual GrTexture* asTexture() SK_OVERRIDE { return this; }
virtual const GrTexture* asTexture() const SK_OVERRIDE { return this; }
virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE { return fRenderTarget.get(); }

View File

@ -92,12 +92,9 @@ bool GrPlot::addSubImage(int width, int height, const void* image, SkIPoint16* l
// otherwise, just upload the image directly
} else if (image) {
adjust_for_offset(loc, fOffset);
GrContext* context = fTexture->getContext();
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrPlot::uploadToTexture");
context->writeTexturePixels(fTexture,
loc->fX, loc->fY, width, height,
fTexture->config(), image, 0,
GrContext::kDontFlush_PixelOpsFlag);
fTexture->writePixels(loc->fX, loc->fY, width, height, fTexture->config(), image, 0,
GrContext::kDontFlush_PixelOpsFlag);
} else {
adjust_for_offset(loc, fOffset);
}
@ -118,7 +115,6 @@ void GrPlot::uploadToTexture() {
if (fDirty) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrPlot::uploadToTexture");
SkASSERT(fTexture);
GrContext* context = fTexture->getContext();
// We pass the flag that does not force a flush. We assume our caller is
// smart and hasn't referenced the part of the texture we're about to update
// since the last flush.
@ -126,12 +122,9 @@ void GrPlot::uploadToTexture() {
const unsigned char* dataPtr = fPlotData;
dataPtr += rowBytes*fDirtyRect.fTop;
dataPtr += fBytesPerPixel*fDirtyRect.fLeft;
context->writeTexturePixels(fTexture,
fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
fDirtyRect.width(), fDirtyRect.height(),
fTexture->config(), dataPtr,
rowBytes,
GrContext::kDontFlush_PixelOpsFlag);
fTexture->writePixels(fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
fDirtyRect.width(), fDirtyRect.height(), fTexture->config(), dataPtr,
rowBytes, GrContext::kDontFlush_PixelOpsFlag);
fDirtyRect.setEmpty();
fDirty = false;
// If the Plot is nearly full, anything else we add will probably be small and one

View File

@ -35,6 +35,7 @@
#include "GrTraceMarker.h"
#include "GrTracing.h"
#include "SkDashPathPriv.h"
#include "SkConfig8888.h"
#include "SkGr.h"
#include "SkRTConf.h"
#include "SkRRect.h"
@ -1244,72 +1245,140 @@ void GrContext::flush(int flagsBitfield) {
fFlushToReduceCacheSize = false;
}
bool GrContext::writeTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, const void* buffer, size_t rowBytes,
uint32_t flags) {
ASSERT_OWNED_RESOURCE(texture);
if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture, config)) {
if (texture->asRenderTarget()) {
return this->writeRenderTargetPixels(texture->asRenderTarget(),
left, top, width, height,
config, buffer, rowBytes, flags);
} else {
return false;
}
}
if (!(kDontFlush_PixelOpsFlag & flags) && texture->surfacePriv().hasPendingIO()) {
this->flush();
}
return fGpu->writeTexturePixels(texture, left, top, width, height,
config, buffer, rowBytes);
// No need to check the kFlushWrites flag here since we issued the write directly to fGpu.
}
bool GrContext::readTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer, size_t rowBytes,
uint32_t flags) {
ASSERT_OWNED_RESOURCE(texture);
GrRenderTarget* target = texture->asRenderTarget();
if (target) {
return this->readRenderTargetPixels(target,
left, top, width, height,
config, buffer, rowBytes,
flags);
} else {
// TODO: make this more efficient for cases where we're reading the entire
// texture, i.e., use GetTexImage() instead
// create scratch rendertarget and read from that
GrAutoScratchTexture ast;
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit;
desc.fWidth = width;
desc.fHeight = height;
desc.fConfig = config;
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
ast.set(this, desc, kExact_ScratchTexMatch);
GrTexture* dst = ast.texture();
if (dst && (target = dst->asRenderTarget())) {
this->copySurface(target, texture, SkIRect::MakeXYWH(top, left, width, height),
SkIPoint::Make(0,0));
return this->readRenderTargetPixels(target,
left, top, width, height,
config, buffer, rowBytes,
flags);
}
bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
const void* inPixels, size_t outRowBytes, void* outPixels) {
SkSrcPixelInfo srcPI;
if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
return false;
}
srcPI.fAlphaType = kUnpremul_SkAlphaType;
srcPI.fPixels = inPixels;
srcPI.fRowBytes = inRowBytes;
SkDstPixelInfo dstPI;
dstPI.fColorType = srcPI.fColorType;
dstPI.fAlphaType = kPremul_SkAlphaType;
dstPI.fPixels = outPixels;
dstPI.fRowBytes = outRowBytes;
return srcPI.convertPixelsTo(&dstPI, width, height);
}
#include "SkConfig8888.h"
bool GrContext::writeSurfacePixels(GrSurface* surface,
int left, int top, int width, int height,
GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
uint32_t pixelOpsFlags) {
{
GrTexture* texture = NULL;
if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) &&
fGpu->canWriteTexturePixels(texture, srcConfig)) {
if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
surface->surfacePriv().hasPendingIO()) {
this->flush();
}
return fGpu->writeTexturePixels(texture, left, top, width, height,
srcConfig, buffer, rowBytes);
// Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the
// upload is already flushed.
}
}
// If we didn't do a direct texture write then we upload the pixels to a texture and draw.
GrRenderTarget* renderTarget = surface->asRenderTarget();
if (NULL == renderTarget) {
return false;
}
// We ignore the preferred config unless it is a R/B swap of the src config. In that case
// we will upload the original src data to a scratch texture but we will spoof it as the swapped
// config. This scratch will then have R and B swapped. We correct for this by swapping again
// when drawing the scratch to the dst using a conversion effect.
bool swapRAndB = false;
GrPixelConfig writeConfig = srcConfig;
if (GrPixelConfigSwapRAndB(srcConfig) ==
fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
writeConfig = GrPixelConfigSwapRAndB(srcConfig);
swapRAndB = true;
}
GrTextureDesc desc;
desc.fWidth = width;
desc.fHeight = height;
desc.fConfig = writeConfig;
GrAutoScratchTexture ast(this, desc);
GrTexture* texture = ast.texture();
if (NULL == texture) {
return false;
}
SkAutoTUnref<const GrFragmentProcessor> fp;
SkMatrix textureMatrix;
textureMatrix.setIDiv(texture->width(), texture->height());
// allocate a tmp buffer and sw convert the pixels to premul
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
if (!GrPixelConfigIs8888(srcConfig)) {
return false;
}
fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
// handle the unpremul step on the CPU if we couldn't create an effect to do it.
if (NULL == fp) {
size_t tmpRowBytes = 4 * width;
tmpPixels.reset(width * height);
if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
tmpPixels.get())) {
return false;
}
rowBytes = tmpRowBytes;
buffer = tmpPixels.get();
}
}
if (NULL == fp) {
fp.reset(GrConfigConversionEffect::Create(texture,
swapRAndB,
GrConfigConversionEffect::kNone_PMConversion,
textureMatrix));
}
// Even if the client told us not to flush, we still flush here. The client may have known that
// writes to the original surface caused no data hazards, but they can't know that the scratch
// we just got is safe.
if (texture->surfacePriv().hasPendingIO()) {
this->flush();
}
if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
writeConfig, buffer, rowBytes)) {
return false;
}
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
// This function can be called in the midst of drawing another object (e.g., when uploading a
// SW-rasterized clip while issuing a draw). So we push the current geometry state before
// drawing a rect to the render target.
// The bracket ensures we pop the stack if we wind up flushing below.
{
GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL);
GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kReset_ASRInit,
&matrix);
GrDrawState* drawState = drawTarget->drawState();
drawState->addColorProcessor(fp);
drawState->setRenderTarget(renderTarget);
drawState->disableState(GrDrawState::kClip_StateBit);
drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)));
}
if (kFlushWrites_PixelOp & pixelOpsFlags) {
this->flushSurfaceWrites(surface);
}
return true;
}
// toggles between RGBA and BGRA
static SkColorType toggle_colortype32(SkColorType ct) {
@ -1372,8 +1441,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
GrTexture* src = target->asTexture();
GrAutoScratchTexture ast;
if (src && (swapRAndB || unpremul || flipY)) {
// Make the scratch a render target because we don't have a robust readTexturePixels as of
// yet. It calls this function.
// Make the scratch a render so we can read its pixels.
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit;
desc.fWidth = width;
@ -1508,144 +1576,6 @@ void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe
}
}
bool GrContext::writeRenderTargetPixels(GrRenderTarget* renderTarget,
int left, int top, int width, int height,
GrPixelConfig srcConfig,
const void* buffer,
size_t rowBytes,
uint32_t pixelOpsFlags) {
ASSERT_OWNED_RESOURCE(renderTarget);
if (NULL == renderTarget) {
renderTarget = fRenderTarget.get();
if (NULL == renderTarget) {
return false;
}
}
// TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
// desktop GL).
// We will always call some form of writeTexturePixels and we will pass our flags on to it.
// Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
// set.)
// If the RT is also a texture and we don't have to premultiply then take the texture path.
// We expect to be at least as fast or faster since it doesn't use an intermediate texture as
// we do below.
#if !defined(SK_BUILD_FOR_MAC)
// At least some drivers on the Mac get confused when glTexImage2D is called on a texture
// attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
// HW is affected.
if (renderTarget->asTexture() && !(kUnpremul_PixelOpsFlag & pixelOpsFlags) &&
fGpu->canWriteTexturePixels(renderTarget->asTexture(), srcConfig)) {
return this->writeTexturePixels(renderTarget->asTexture(),
left, top, width, height,
srcConfig, buffer, rowBytes, pixelOpsFlags);
}
#endif
// We ignore the preferred config unless it is a R/B swap of the src config. In that case
// we will upload the original src data to a scratch texture but we will spoof it as the swapped
// config. This scratch will then have R and B swapped. We correct for this by swapping again
// when drawing the scratch to the dst using a conversion effect.
bool swapRAndB = false;
GrPixelConfig writeConfig = srcConfig;
if (GrPixelConfigSwapRAndB(srcConfig) ==
fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
writeConfig = GrPixelConfigSwapRAndB(srcConfig);
swapRAndB = true;
}
GrTextureDesc desc;
desc.fWidth = width;
desc.fHeight = height;
desc.fConfig = writeConfig;
GrAutoScratchTexture ast(this, desc);
GrTexture* texture = ast.texture();
if (NULL == texture) {
return false;
}
SkAutoTUnref<const GrFragmentProcessor> fp;
SkMatrix textureMatrix;
textureMatrix.setIDiv(texture->width(), texture->height());
// allocate a tmp buffer and sw convert the pixels to premul
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
if (!GrPixelConfigIs8888(srcConfig)) {
return false;
}
fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
// handle the unpremul step on the CPU if we couldn't create an effect to do it.
if (NULL == fp) {
SkSrcPixelInfo srcPI;
if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
return false;
}
srcPI.fAlphaType = kUnpremul_SkAlphaType;
srcPI.fPixels = buffer;
srcPI.fRowBytes = rowBytes;
tmpPixels.reset(width * height);
SkDstPixelInfo dstPI;
dstPI.fColorType = srcPI.fColorType;
dstPI.fAlphaType = kPremul_SkAlphaType;
dstPI.fPixels = tmpPixels.get();
dstPI.fRowBytes = 4 * width;
if (!srcPI.convertPixelsTo(&dstPI, width, height)) {
return false;
}
buffer = tmpPixels.get();
rowBytes = 4 * width;
}
}
if (NULL == fp) {
fp.reset(GrConfigConversionEffect::Create(texture,
swapRAndB,
GrConfigConversionEffect::kNone_PMConversion,
textureMatrix));
}
if (!this->writeTexturePixels(texture,
0, 0, width, height,
writeConfig, buffer, rowBytes,
pixelOpsFlags & ~kUnpremul_PixelOpsFlag)) {
return false;
}
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
// This function can be called in the midst of drawing another object (e.g., when uploading a
// SW-rasterized clip while issuing a draw). So we push the current geometry state before
// drawing a rect to the render target.
// The bracket ensures we pop the stack if we wind up flushing below.
{
GrDrawTarget* drawTarget = this->prepareToDraw(NULL, kYes_BufferedDraw, NULL, NULL);
GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kReset_ASRInit,
&matrix);
GrDrawState* drawState = drawTarget->drawState();
drawState->addColorProcessor(fp);
drawState->setRenderTarget(renderTarget);
drawState->disableState(GrDrawState::kClip_StateBit);
drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)));
}
if (kFlushWrites_PixelOp & pixelOpsFlags) {
this->flush();
}
return true;
}
void GrContext::flushSurfaceWrites(GrSurface* surface) {
if (surface->surfacePriv().hasPendingWrite()) {
this->flush();

View File

@ -190,10 +190,9 @@ static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
return;
}
context->writeTexturePixels(*gammaTexture,
0, 0, width, height,
(*gammaTexture)->config(), data.get(), 0,
GrContext::kDontFlush_PixelOpsFlag);
(*gammaTexture)->writePixels(0, 0, width, height,
(*gammaTexture)->config(), data.get(), 0,
GrContext::kDontFlush_PixelOpsFlag);
}
}

View File

@ -13,38 +13,6 @@
#include "GrGpu.h"
#include "GrStencilBuffer.h"
bool GrRenderTarget::readPixels(int left, int top, int width, int height,
GrPixelConfig config,
void* buffer,
size_t rowBytes,
uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return false;
}
return context->readRenderTargetPixels(this,
left, top, width, height,
config, buffer, rowBytes,
pixelOpsFlags);
}
void GrRenderTarget::writePixels(int left, int top, int width, int height,
GrPixelConfig config,
const void* buffer,
size_t rowBytes,
uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return;
}
context->writeRenderTargetPixels(this,
left, top, width, height,
config, buffer, rowBytes,
pixelOpsFlags);
}
void GrRenderTarget::resolve() {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();

View File

@ -13,6 +13,34 @@
#include "SkImageEncoder.h"
#include <stdio.h>
bool GrSurface::writePixels(int left, int top, int width, int height,
GrPixelConfig config, const void* buffer, size_t rowBytes,
uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return false;
}
return context->writeSurfacePixels(this, left, top, width, height, config, buffer, rowBytes,
pixelOpsFlags);
}
bool GrSurface::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer, size_t rowBytes,
uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return false;
}
GrRenderTarget* target = this->asRenderTarget();
if (target) {
return context->readRenderTargetPixels(target, left, top, width, height, config, buffer,
rowBytes, pixelOpsFlags);
}
return false;
}
SkImageInfo GrSurface::info() const {
SkColorType colorType;
if (!GrPixelConfig2ColorType(this->config(), &colorType)) {

View File

@ -53,33 +53,6 @@ size_t GrTexture::gpuMemorySize() const {
return textureSize;
}
bool GrTexture::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer,
size_t rowBytes, uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return false;
}
return context->readTexturePixels(this,
left, top, width, height,
config, buffer, rowBytes,
pixelOpsFlags);
}
void GrTexture::writePixels(int left, int top, int width, int height,
GrPixelConfig config, const void* buffer,
size_t rowBytes, uint32_t pixelOpsFlags) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getContext();
if (NULL == context) {
return;
}
context->writeTexturePixels(this,
left, top, width, height,
config, buffer, rowBytes,
pixelOpsFlags);
}
void GrTexture::onRelease() {
SkASSERT(!this->texturePriv().isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));

View File

@ -254,9 +254,8 @@ static GrTexture *load_yuv_texture(GrContext* ctx, bool cache, const GrTexturePa
yuvDesc.fHeight = yuvSizes[i].fHeight;
yuvTextures[i].set(ctx, yuvDesc);
if ((NULL == yuvTextures[i].texture()) ||
!ctx->writeTexturePixels(yuvTextures[i].texture(),
0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
yuvDesc.fConfig, planes[i], rowBytes[i])) {
!yuvTextures[i].texture()->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
yuvDesc.fConfig, planes[i], rowBytes[i])) {
return NULL;
}
}

View File

@ -155,13 +155,12 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
// Pass in the kDontFlush flag, since we know we're writing to a part of this texture
// that is not currently in use
fDesc.fContext->writeTexturePixels(fTexture,
0, rowNumber * fDesc.fRowHeight,
fDesc.fWidth, fDesc.fRowHeight,
SkImageInfo2GrPixelConfig(data.info()),
data.getPixels(),
data.rowBytes(),
GrContext::kDontFlush_PixelOpsFlag);
fTexture->writePixels(0, rowNumber * fDesc.fRowHeight,
fDesc.fWidth, fDesc.fRowHeight,
SkImageInfo2GrPixelConfig(data.info()),
data.getPixels(),
data.rowBytes(),
GrContext::kDontFlush_PixelOpsFlag);
}
SkASSERT(rowNumber >= 0);

View File

@ -68,9 +68,8 @@ DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
}
// write square
context->writeTexturePixels(fpTexture, 0, 0, DEV_W, DEV_H, desc.fConfig,
controlPixelData, 0);
context->readTexturePixels(fpTexture, 0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer, 0);
fpTexture->writePixels(0, 0, DEV_W, DEV_H, desc.fConfig, controlPixelData, 0);
fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer, 0);
for (int j = 0; j < FP_CONTROL_ARRAY_SIZE; ++j) {
REPORTER_ASSERT(reporter, readBuffer[j] == controlPixelData[j]);
}