Adds read pixels to GrTexture and GrRenderTarget

Adds SkGrRenderTargetPixelRef for SkBitmaps that are backed by RTs that aren't textures.
Adds onReadPixels implementations for SkGr pixel ref types



git-svn-id: http://skia.googlecode.com/svn/trunk@1056 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-04-05 17:08:27 +00:00
parent 62ab7addb0
commit 669fdc4ed8
24 changed files with 417 additions and 181 deletions

View File

@ -423,20 +423,49 @@ public:
* FlushBits.
*/
void flush(int flagsBitfield = 0);
/**
* Return true on success, i.e. if we could copy the specified range of
* pixels from the current render-target into the buffer, converting into
* the specified pixel-config.
* Reads a rectangle of pixels from a render target.
* @param renderTarget the render target to read from. NULL means the
* current render target.
* @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.
*
* @return true if the read succeeded, false if not. The read can fail
* because of a unsupported pixel config or because no render
* target is currently set.
*/
bool readPixels(int left, int top, int width, int height,
GrTexture::PixelConfig, void* buffer);
bool readRenderTargetPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer);
/**
* Reads a rectangle of pixels from a texture.
* @param texture the render target 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.
*
* @return true if the read succeeded, false if not. The read can fail
* because of a unsupported pixel config.
*/
bool readTexturePixels(GrTexture* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer);
/**
* Copy the src pixels [buffer, stride, pixelconfig] into the current
* render-target at the specified rectangle.
*/
void writePixels(int left, int top, int width, int height,
GrTexture::PixelConfig, const void* buffer, size_t stride);
GrPixelConfig, const void* buffer, size_t stride);
///////////////////////////////////////////////////////////////////////////

View File

@ -180,17 +180,17 @@ public:
protected:
struct GLTextureDesc {
uint32_t fContentWidth;
uint32_t fContentHeight;
uint32_t fAllocWidth;
uint32_t fAllocHeight;
PixelConfig fFormat;
GrGLuint fTextureID;
GrGLenum fUploadFormat;
GrGLenum fUploadByteCount;
GrGLenum fUploadType;
GrGLuint fStencilBits;
Orientation fOrientation;
uint32_t fContentWidth;
uint32_t fContentHeight;
uint32_t fAllocWidth;
uint32_t fAllocHeight;
GrPixelConfig fFormat;
GrGLuint fTextureID;
GrGLenum fUploadFormat;
GrGLenum fUploadByteCount;
GrGLenum fUploadType;
GrGLuint fStencilBits;
Orientation fOrientation;
};
typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs;
GrGLTexture(GrGpuGL* gpu,

View File

@ -17,15 +17,16 @@
#ifndef GrGpu_DEFINED
#define GrGpu_DEFINED
#include "GrDrawTarget.h"
#include "GrPathRenderer.h"
#include "GrRect.h"
#include "GrRefCnt.h"
#include "GrDrawTarget.h"
#include "GrTexture.h"
#include "GrPathRenderer.h"
class GrVertexBufferAllocPool;
class GrContext;
class GrIndexBufferAllocPool;
class GrResource;
class GrVertexBufferAllocPool;
class GrGpu : public GrDrawTarget {
@ -104,7 +105,7 @@ public:
// kRenderTarget_TextureFlag.
uint32_t fWidth; //!< Width of the texture
uint32_t fHeight; //!< Height of the texture
GrTexture::PixelConfig fFormat; //!< Format of source data of the
GrPixelConfig fFormat; //!< Format of source data of the
// texture. Not guaraunteed to be the
// same as internal format used by
// 3D API.
@ -143,6 +144,14 @@ public:
GrGpu();
virtual ~GrGpu();
// The GrContext sets itself as the owner of this Gpu object
void setContext(GrContext* context) {
GrAssert(NULL == fContext);
fContext = context;
}
GrContext* getContext() { return fContext; }
const GrContext* getContext() const { return fContext; }
/**
* The GrGpu object normally assumes that no outsider is setting state
* within the underlying 3D API's context/device/whatever. This call informs
@ -340,19 +349,23 @@ public:
void forceRenderTargetFlush();
/**
* Reads a rectangle of pixels from the current render target.
* @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 buffer memory to read the rectangle into.
* Reads a rectangle of pixels from a render target.
* @param renderTarget the render target to read from. NULL means the
* current render target.
* @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.
*
* @return true if the read succeeded, false if not. The read can fail
* because of a unsupported pixel config or because no render
* target is currently set.
*/
bool readPixels(int left, int top, int width, int height,
GrTexture::PixelConfig, void* buffer);
bool readPixels(GrRenderTarget* renderTarget,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer);
const Stats& getStats() const;
void resetStats();
@ -499,7 +512,7 @@ protected:
// overridden by API-specific derived class to perform the read pixels.
virtual bool readPixelsHelper(int left, int top, int width, int height,
GrTexture::PixelConfig, void* buffer) = 0;
GrPixelConfig, void* buffer) = 0;
// called to program the vertex data, indexCount will be 0 if drawing non-
// indexed geometry. The subclass may adjust the startVertex and/or
@ -523,20 +536,7 @@ protected:
virtual void eraseStencilClip(const GrIRect& rect) = 0;
private:
// readies the pools to provide vertex/index data.
void prepareVertexPool();
void prepareIndexPool();
// determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrPathIter* path,
GrPathFill fill);
void handleDirtyContext() {
if (fContextIsDirty) {
this->resetContext();
fContextIsDirty = false;
}
}
GrContext* fContext; // not reffed (context refs gpu)
GrVertexBufferAllocPool* fVertexPool;
@ -561,6 +561,21 @@ private:
GrResource* fResourceHead;
// readies the pools to provide vertex/index data.
void prepareVertexPool();
void prepareIndexPool();
// determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrPathIter* path,
GrPathFill fill);
void handleDirtyContext() {
if (fContextIsDirty) {
this->resetContext();
fContextIsDirty = false;
}
}
// used to save and restore state when the GrGpu needs
// to make its geometry pools available internally
class AutoInternalDrawGeomRestore {

View File

@ -52,6 +52,21 @@ public:
*/
GrTexture* asTexture() {return fTexture;}
/**
* Reads a rectangle of pixels from the render target.
* @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.
*
* @return true if the read succeeded, false if not. The read can fail
* because of a unsupported pixel config.
*/
bool readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer);
protected:
GrRenderTarget(GrGpu* gpu,
GrTexture* texture,
@ -81,25 +96,11 @@ private:
};
class GrTexture : public GrResource {
public:
enum PixelConfig {
kUnknown_PixelConfig,
kAlpha_8_PixelConfig,
kIndex_8_PixelConfig,
kRGB_565_PixelConfig,
kRGBA_4444_PixelConfig, //!< premultiplied
kRGBA_8888_PixelConfig, //!< premultiplied
kRGBX_8888_PixelConfig, //!< treat the alpha channel as opaque
};
static size_t BytesPerPixel(PixelConfig);
static bool PixelConfigIsOpaque(PixelConfig);
static bool PixelConfigIsAlphaOnly(PixelConfig);
protected:
GrTexture(GrGpu* gpu,
int width,
int height,
PixelConfig config)
GrPixelConfig config)
: INHERITED(gpu)
, fWidth(width)
, fHeight(height)
@ -138,13 +139,13 @@ public:
/**
* Retrieves the pixel config specified when the texture was created.
*/
PixelConfig config() const { return fConfig; }
GrPixelConfig config() const { return fConfig; }
/**
* Approximate number of bytes used by the texture
*/
size_t sizeInBytes() const {
return fWidth * fHeight * BytesPerPixel(fConfig);
return fWidth * fHeight * GrBytesPerPixel(fConfig);
}
/**
@ -163,6 +164,21 @@ public:
uint32_t height,
const void* srcData) = 0;
/**
* Reads a rectangle of pixels from the texture.
* @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.
*
* @return true if the read succeeded, false if not. The read can fail
* because of a unsupported pixel config.
*/
bool readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer);
/**
* Retrieves the render target underlying this texture that can be passed to
* GrGpu::setRenderTarget().
@ -200,7 +216,8 @@ private:
// for this texture if the texture is power of two sized.
int fShiftFixedX;
int fShiftFixedY;
PixelConfig fConfig;
GrPixelConfig fConfig;
typedef GrResource INHERITED;
};

View File

@ -212,6 +212,54 @@ static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
return (int)format + 1;
}
/**
* Pixel configurations.
*/
enum GrPixelConfig {
kUnknown_GrPixelConfig,
kAlpha_8_GrPixelConfig,
kIndex_8_GrPixelConfig,
kRGB_565_GrPixelConfig,
kRGBA_4444_GrPixelConfig, //!< premultiplied
kRGBA_8888_GrPixelConfig, //!< premultiplied
kRGBX_8888_GrPixelConfig, //!< treat the alpha channel as opaque
};
static inline size_t GrBytesPerPixel(GrPixelConfig config) {
switch (config) {
case kAlpha_8_GrPixelConfig:
case kIndex_8_GrPixelConfig:
return 1;
case kRGB_565_GrPixelConfig:
case kRGBA_4444_GrPixelConfig:
return 2;
case kRGBA_8888_GrPixelConfig:
case kRGBX_8888_GrPixelConfig:
return 4;
default:
return 0;
}
}
static inline bool GrPixelConfigIsOpaque(GrPixelConfig config) {
switch (config) {
case kRGB_565_GrPixelConfig:
case kRGBX_8888_GrPixelConfig:
return true;
default:
return false;
}
}
static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
switch (config) {
case kAlpha_8_GrPixelConfig:
return true;
default:
return false;
}
}
/**
* Set Operations used to construct clips.
*/

View File

@ -142,16 +142,16 @@ GrAtlasMgr::~GrAtlasMgr() {
fGpu->unref();
}
static GrTexture::PixelConfig maskformat2pixelconfig(GrMaskFormat format) {
static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
switch (format) {
case kA8_GrMaskFormat:
return GrTexture::kAlpha_8_PixelConfig;
return kAlpha_8_GrPixelConfig;
case kA565_GrMaskFormat:
return GrTexture::kRGB_565_PixelConfig;
return kRGB_565_GrPixelConfig;
default:
GrAssert(!"unknown maskformat");
}
return GrTexture::kUnknown_PixelConfig;
return kUnknown_GrPixelConfig;
}
GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,

View File

@ -206,7 +206,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
// no longer need to clamp at min RT size.
rtDesc.fWidth = GrNextPow2(desc.fWidth);
rtDesc.fHeight = GrNextPow2(desc.fHeight);
int bpp = GrTexture::BytesPerPixel(desc.fFormat);
int bpp = GrBytesPerPixel(desc.fFormat);
GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
rtDesc.fWidth *
rtDesc.fHeight);
@ -609,14 +609,39 @@ void GrContext::flushDrawBuffer() {
#endif
}
bool GrContext::readPixels(int left, int top, int width, int height,
GrTexture::PixelConfig config, void* buffer) {
this->flush(true);
return fGpu->readPixels(left, top, width, height, config, buffer);
bool GrContext::readTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
// TODO: code read pixels for textures that aren't rendertargets
this->flush();
GrRenderTarget* target = texture->asRenderTarget();
if (NULL != target) {
return fGpu->readPixels(target,
left, top, width, height,
config, buffer);
} else {
return false;
}
}
bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
uint32_t flushFlags = 0;
if (NULL == target) {
flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit;
}
this->flush(flushFlags);
return fGpu->readPixels(target,
left, top, width, height,
config, buffer);
}
void GrContext::writePixels(int left, int top, int width, int height,
GrTexture::PixelConfig config, const void* buffer,
GrPixelConfig config, const void* buffer,
size_t stride) {
// TODO: when underlying api has a direct way to do this we should use it
@ -764,6 +789,7 @@ GrContext::GrContext(GrGpu* gpu) :
fGpu = gpu;
fGpu->ref();
fGpu->setContext(this);
fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
fGpu->setClipPathRenderer(fCustomPathRenderer);

View File

@ -492,10 +492,10 @@ bool GrDrawTarget::canDisableBlend() const {
for (int s = 0; s < kNumStages; ++s) {
if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
GrAssert(NULL != fCurrDrawState.fTextures[s]);
GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
if (GrTexture::kRGB_565_PixelConfig != config &&
GrTexture::kRGBX_8888_PixelConfig != config) {
if (kRGB_565_GrPixelConfig != config &&
kRGBX_8888_GrPixelConfig != config) {
return false;
}
}

View File

@ -28,42 +28,6 @@
static const size_t VERTEX_POOL_VB_SIZE = 1 << 12;
static const int VERTEX_POOL_VB_COUNT = 1;
////////////////////////////////////////////////////////////////////////////////
size_t GrTexture::BytesPerPixel(PixelConfig config) {
switch (config) {
case kAlpha_8_PixelConfig:
case kIndex_8_PixelConfig:
return 1;
case kRGB_565_PixelConfig:
case kRGBA_4444_PixelConfig:
return 2;
case kRGBA_8888_PixelConfig:
case kRGBX_8888_PixelConfig:
return 4;
default:
return 0;
}
}
bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
switch (config) {
case GrTexture::kRGB_565_PixelConfig:
case GrTexture::kRGBX_8888_PixelConfig:
return true;
default:
return false;
}
}
bool GrTexture::PixelConfigIsAlphaOnly(PixelConfig config) {
switch (config) {
case GrTexture::kAlpha_8_PixelConfig:
return true;
default:
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
@ -75,6 +39,7 @@ GrGpu::GrGpu()
, fCurrPoolStartVertex(0)
, fCurrPoolIndexBuffer(NULL)
, fCurrPoolStartIndex(0)
, fContext(NULL)
, fVertexPool(NULL)
, fIndexPool(NULL)
, fQuadIndexBuffer(NULL)
@ -85,6 +50,7 @@ GrGpu::GrGpu()
, fVertexPoolInUse(false)
, fIndexPoolInUse(false)
, fResourceHead(NULL) {
#if GR_DEBUG
//gr_run_unittests();
#endif
@ -210,10 +176,17 @@ void GrGpu::forceRenderTargetFlush() {
this->forceRenderTargetFlushHelper();
}
bool GrGpu::readPixels(int left, int top, int width, int height,
GrTexture::PixelConfig config, void* buffer) {
bool GrGpu::readPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
this->handleDirtyContext();
GrRenderTarget* prevTarget = fCurrDrawState.fRenderTarget;
if (NULL != target) {
fCurrDrawState.fRenderTarget = target;
}
return this->readPixelsHelper(left, top, width, height, config, buffer);
fCurrDrawState.fRenderTarget = prevTarget;
}
////////////////////////////////////////////////////////////////////////////////
@ -775,12 +748,6 @@ void GrGpu::printStats() const {
}
////////////////////////////////////////////////////////////////////////////////
GrTexture::~GrTexture() {
// use this to set a break-point if needed
// Gr_clz(3);
}
const GrSamplerState GrSamplerState::gClampNoFilter(
GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,

View File

@ -666,7 +666,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
return return_null_texture();
}
glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
// in case we need a temporary, trimmed copy of the src pixels
GrAutoSMalloc<128 * 128> trimStorage;
@ -728,7 +728,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
DEFAULT_PARAMS.fWrapT));
GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
if (kIndex_8_GrPixelConfig == desc.fFormat &&
supports8BitPalette()) {
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
GrAssert(desc.fWidth == glDesc.fAllocWidth);
@ -1155,7 +1155,7 @@ void GrGpuGL::forceRenderTargetFlushHelper() {
}
bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
GrTexture::PixelConfig config, void* buffer) {
GrPixelConfig config, void* buffer) {
GrGLenum internalFormat; // we don't use this for glReadPixels
GrGLenum format;
GrGLenum type;
@ -1180,7 +1180,7 @@ bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
// now reverse the order of the rows, since GL's are bottom-to-top, but our
// API presents top-to-bottom
{
size_t stride = width * GrTexture::BytesPerPixel(config);
size_t stride = width * GrBytesPerPixel(config);
GrAutoMalloc rowStorage(stride);
void* tmp = rowStorage.get();
@ -1767,13 +1767,13 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
}
}
bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
bool GrGpuGL::canBeTexture(GrPixelConfig config,
GrGLenum* internalFormat,
GrGLenum* format,
GrGLenum* type) {
switch (config) {
case GrTexture::kRGBA_8888_PixelConfig:
case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
case kRGBA_8888_GrPixelConfig:
case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
*format = GR_GL_32BPP_COLOR_FORMAT;
if (GR_GL_SUPPORT_ES) {
// according to GL_EXT_texture_format_BGRA8888 the *internal*
@ -1784,17 +1784,17 @@ bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
}
*type = GR_GL_UNSIGNED_BYTE;
break;
case GrTexture::kRGB_565_PixelConfig:
case kRGB_565_GrPixelConfig:
*format = GR_GL_RGB;
*internalFormat = GR_GL_RGB;
*type = GR_GL_UNSIGNED_SHORT_5_6_5;
break;
case GrTexture::kRGBA_4444_PixelConfig:
case kRGBA_4444_GrPixelConfig:
*format = GR_GL_RGBA;
*internalFormat = GR_GL_RGBA;
*type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
break;
case GrTexture::kIndex_8_PixelConfig:
case kIndex_8_GrPixelConfig:
if (this->supports8BitPalette()) {
*format = GR_GL_PALETTE8_RGBA8;
*internalFormat = GR_GL_PALETTE8_RGBA8;
@ -1803,7 +1803,7 @@ bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
return false;
}
break;
case GrTexture::kAlpha_8_PixelConfig:
case kAlpha_8_GrPixelConfig:
*format = GR_GL_ALPHA;
*internalFormat = GR_GL_ALPHA;
*type = GR_GL_UNSIGNED_BYTE;
@ -1835,23 +1835,23 @@ void GrGpuGL::setSpareTextureUnit() {
RenderBufferStorage* has to be a specific format (not a base format like
GL_RGBA).
*/
bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format) {
bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
switch (config) {
case GrTexture::kRGBA_8888_PixelConfig:
case GrTexture::kRGBX_8888_PixelConfig:
case kRGBA_8888_GrPixelConfig:
case kRGBX_8888_GrPixelConfig:
if (fRGBA8Renderbuffer) {
*format = GR_GL_RGBA8;
return true;
} else {
return false;
}
case GrTexture::kRGB_565_PixelConfig:
case kRGB_565_GrPixelConfig:
GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
// with FBO extension desktop GL has
// no such internal format
*format = GR_GL_RGB565;
return true;
case GrTexture::kRGBA_4444_PixelConfig:
case kRGBA_4444_GrPixelConfig:
*format = GR_GL_RGBA4;
return true;
default:

View File

@ -87,7 +87,7 @@ protected:
virtual void forceRenderTargetFlushHelper();
virtual bool readPixelsHelper(int left, int top, int width, int height,
GrTexture::PixelConfig, void* buffer);
GrPixelConfig, void* buffer);
virtual void drawIndexedHelper(GrPrimitiveType type,
uint32_t startVertex,
@ -149,11 +149,11 @@ private:
void flushStencil();
void resolveTextureRenderTarget(GrGLTexture* texture);
bool canBeTexture(GrTexture::PixelConfig config,
bool canBeTexture(GrPixelConfig config,
GrGLenum* internalFormat,
GrGLenum* format,
GrGLenum* type);
bool fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format);
bool fboInternalFormat(GrPixelConfig config, GrGLenum* format);
friend class GrGLVertexBuffer;
friend class GrGLIndexBuffer;

View File

@ -192,7 +192,7 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
if (NULL != texture) {
TextureEnvRGBOperands nextRGBOperand0 =
(texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
(GrPixelConfigIsAlphaOnly(texture->config())) ?
kAlpha_TextureEnvRGBOperand :
kColor_TextureEnvRGBOperand;
if (fHWRGBOperand0[s] != nextRGBOperand0) {

View File

@ -508,7 +508,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
break;
}
if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
if (GrPixelConfigIsAlphaOnly(texture->config())) {
stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation;
} else {
stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation;

View File

@ -1042,7 +1042,7 @@ void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc
GrAssert(!"Unexpected sample mode!");
break;
}
if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
if (GrPixelConfigIsAlphaOnly(texture->config())) {
stage.fModulation = StageDesc::kAlpha_Modulation;
} else {
stage.fModulation = StageDesc::kColor_Modulation;

View File

@ -47,7 +47,7 @@ void GrTextContext::flushGlyphs() {
GrAssert(fCurrTexture);
fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture);
if (!GrTexture::PixelConfigIsAlphaOnly(fCurrTexture->config())) {
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
kISA_BlendCoeff != fPaint.fDstBlendCoeff ||
NULL != fPaint.getTexture()) {

45
gpu/src/GrTexture.cpp Normal file
View File

@ -0,0 +1,45 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "GrTexture.h"
#include "GrContext.h"
bool GrRenderTarget::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getGpu()->getContext();
GrAssert(NULL != context);
return context->readRenderTargetPixels(this,
left, top,
width, height,
config, buffer);
}
GrTexture::~GrTexture() {
// use this to set a break-point if needed
// Gr_clz(3);
}
bool GrTexture::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
// go through context so that all necessary flushing occurs
GrContext* context = this->getGpu()->getContext();
GrAssert(NULL != context);
return context->readTexturePixels(this,
left, top,
width, height,
config, buffer);
}

View File

@ -990,6 +990,7 @@
'../gpu/src/GrTextContext.cpp',
'../gpu/src/GrTextStrike.cpp',
'../gpu/src/GrTextStrike_impl.h',
'../gpu/src/GrTexture.cpp',
'../gpu/src/GrTextureCache.cpp',
'../gpu/src/gr_unittests.cpp',

View File

@ -129,10 +129,10 @@ public:
* Convert the SkBitmap::Config to the corresponding PixelConfig, or
* kUnknown_PixelConfig if the conversion cannot be done.
*/
static GrTexture::PixelConfig BitmapConfig2PixelConfig(SkBitmap::Config,
bool isOpaque);
static GrPixelConfig BitmapConfig2PixelConfig(SkBitmap::Config,
bool isOpaque);
static GrTexture::PixelConfig Bitmap2PixelConfig(const SkBitmap& bm) {
static GrPixelConfig Bitmap2PixelConfig(const SkBitmap& bm) {
return BitmapConfig2PixelConfig(bm.config(), bm.isOpaque());
}

View File

@ -47,5 +47,31 @@ private:
typedef SkPixelRef INHERITED;
};
class SkGrRenderTargetPixelRef : public SkPixelRef {
public:
SkGrRenderTargetPixelRef(GrRenderTarget* rt);
virtual ~SkGrRenderTargetPixelRef();
// override from SkPixelRef
virtual SkGpuTexture* getTexture();
protected:
// override from SkPixelRef
virtual void* onLockPixels(SkColorTable** ptr) {
if (ptr) {
*ptr = NULL;
}
return NULL;
}
// override from SkPixelRef
virtual void onUnlockPixels() {}
virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset);
private:
GrRenderTarget* fRenderTarget;
typedef SkPixelRef INHERITED;
};
#endif

View File

@ -766,17 +766,12 @@ void SampleWindow::afterChildren(SkCanvas* orig) {
SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
SkDevice* device = canvas->getDevice();
SkBitmap bitmap;
SkIRect bounds = {
0, 0,
SkScalarRound(this->width()),
SkScalarRound(this->height())
};
if (device->readPixels(bounds, &bitmap)) {
SkBitmap bmp;
if (device->accessBitmap(false).copyTo(&bmp, SkBitmap::kARGB_8888_Config)) {
static int gSampleGrabCounter;
SkString name;
name.printf("sample_grab_%d", gSampleGrabCounter++);
SkImageEncoder::EncodeFile(name.c_str(), bitmap,
SkImageEncoder::EncodeFile(name.c_str(), bmp,
SkImageEncoder::kPNG_Type, 100);
}
}

View File

@ -869,10 +869,7 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
SkBitmap tmpSrc;
const SkBitmap* src = this;
if (this->getTexture()) {
if (!fPixelRef->readPixels(&tmpSrc)) {
return false;
}
if (fPixelRef && fPixelRef->readPixels(&tmpSrc)) {
SkASSERT(tmpSrc.width() == this->width());
SkASSERT(tmpSrc.height() == this->height());

View File

@ -171,11 +171,15 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
this->width(), this->height());
GrAssert(false);
}
} else if (Current3DApiRenderTarget() == renderTargetOrNull) {
fRenderTarget = fContext->createRenderTargetFrom3DApiState();
} else {
fRenderTarget = renderTargetOrNull;
fRenderTarget->ref();
if (Current3DApiRenderTarget() == renderTargetOrNull) {
fRenderTarget = fContext->createRenderTargetFrom3DApiState();
} else {
fRenderTarget = renderTargetOrNull;
fRenderTarget->ref();
}
SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
this->setPixelRef(pr, 0)->unref();
}
}
@ -233,15 +237,12 @@ bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
}
SkAutoLockPixels alp(tmp);
fContext->setRenderTarget(fRenderTarget);
// we aren't setting the clip or matrix, so mark as dirty
// we don't need to set them for this call and don't have them anyway
fNeedPrepareRenderTarget = true;
if (!fContext->readPixels(bounds.fLeft, bounds.fTop,
bounds.width(), bounds.height(),
GrTexture::kRGBA_8888_PixelConfig,
tmp.getPixels())) {
if (!fContext->readRenderTargetPixels(fRenderTarget,
bounds.fLeft, bounds.fTop,
bounds.width(), bounds.height(),
kRGBA_8888_GrPixelConfig,
tmp.getPixels())) {
return false;
}
@ -254,8 +255,8 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
if (!bitmap.readyToDraw()) {
return;
}
GrTexture::PixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
bitmap.isOpaque());
GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
bitmap.isOpaque());
fContext->setRenderTarget(fRenderTarget);
// we aren't setting the clip or matrix, so mark as dirty
// we don't need to set them for this call and don't have them anyway
@ -709,7 +710,7 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
GrGpu::kNone_AALevel,
dstM.fBounds.width(),
dstM.fBounds.height(),
GrTexture::kAlpha_8_PixelConfig
kAlpha_8_GrPixelConfig
};
GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,

View File

@ -213,25 +213,25 @@ GrPathFill SkGrClipIterator::getPathFill() const {
///////////////////////////////////////////////////////////////////////////////
GrTexture::PixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config,
GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config,
bool isOpaque) {
switch (config) {
case SkBitmap::kA8_Config:
return GrTexture::kAlpha_8_PixelConfig;
return kAlpha_8_GrPixelConfig;
case SkBitmap::kIndex8_Config:
return GrTexture::kIndex_8_PixelConfig;
return kIndex_8_GrPixelConfig;
case SkBitmap::kRGB_565_Config:
return GrTexture::kRGB_565_PixelConfig;
return kRGB_565_GrPixelConfig;
case SkBitmap::kARGB_4444_Config:
return GrTexture::kRGBA_4444_PixelConfig;
return kRGBA_4444_GrPixelConfig;
case SkBitmap::kARGB_8888_Config:
if (isOpaque) {
return GrTexture::kRGBX_8888_PixelConfig;
return kRGBX_8888_GrPixelConfig;
} else {
return GrTexture::kRGBA_8888_PixelConfig;
return kRGBA_8888_GrPixelConfig;
}
default:
return GrTexture::kUnknown_PixelConfig;
return kUnknown_GrPixelConfig;
}
}

View File

@ -16,8 +16,12 @@
#include "SkGrTexturePixelRef.h"
#include "GrTexture.h"
#include "SkRect.h"
#include "SkBitmap.h"
SkGrTexturePixelRef::SkGrTexturePixelRef(GrTexture* tex) {
fTexture = tex;
GrSafeRef(tex);
@ -28,6 +32,71 @@ SkGrTexturePixelRef::~SkGrTexturePixelRef() {
}
bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
return false;
if (NULL != fTexture && fTexture->isValid()) {
int left, top, width, height;
if (NULL != subset) {
left = subset->fLeft;
width = subset->width();
top = subset->fTop;
height = subset->height();
} else {
left = 0;
width = fTexture->width();
top = 0;
height = fTexture->height();
}
dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
dst->allocPixels();
SkAutoLockPixels al(*dst);
void* buffer = dst->getPixels();
return fTexture->readPixels(left, top, width, height,
kRGBA_8888_GrPixelConfig,
buffer);
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
SkGrRenderTargetPixelRef::SkGrRenderTargetPixelRef(GrRenderTarget* rt) {
fRenderTarget = rt;
GrSafeRef(fRenderTarget);
}
SkGrRenderTargetPixelRef::~SkGrRenderTargetPixelRef() {
GrSafeUnref(fRenderTarget);
}
SkGpuTexture* SkGrRenderTargetPixelRef::getTexture() {
if (NULL != fRenderTarget) {
return (SkGpuTexture*) fRenderTarget->asTexture();
}
return NULL;
}
bool SkGrRenderTargetPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
if (NULL != fRenderTarget && fRenderTarget->isValid()) {
int left, top, width, height;
if (NULL != subset) {
left = subset->fLeft;
width = subset->width();
top = subset->fTop;
height = subset->height();
} else {
left = 0;
width = fRenderTarget->width();
top = 0;
height = fRenderTarget->height();
}
dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
dst->allocPixels();
SkAutoLockPixels al(*dst);
void* buffer = dst->getPixels();
return fRenderTarget->readPixels(left, top, width, height,
kRGBA_8888_GrPixelConfig,
buffer);
} else {
return false;
}
}