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
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index cccc14f..c178ed6 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -423,20 +423,49 @@
* 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);
///////////////////////////////////////////////////////////////////////////
diff --git a/gpu/include/GrGLTexture.h b/gpu/include/GrGLTexture.h
index 0624f40..2cd833c 100644
--- a/gpu/include/GrGLTexture.h
+++ b/gpu/include/GrGLTexture.h
@@ -180,17 +180,17 @@
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,
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index c4f5e4b..cbe3e95 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 {
diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h
index d1853e3..2aa80ab 100644
--- a/gpu/include/GrTexture.h
+++ b/gpu/include/GrTexture.h
@@ -52,6 +52,21 @@
*/
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 @@
};
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 @@
/**
* 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);
}
/**
@@ -164,6 +165,21 @@
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 @@
// for this texture if the texture is power of two sized.
int fShiftFixedX;
int fShiftFixedY;
- PixelConfig fConfig;
+
+ GrPixelConfig fConfig;
typedef GrResource INHERITED;
};
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index cc78c3e..2d8c116 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -213,6 +213,54 @@
}
/**
+ * 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.
*/
enum GrSetOp {
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index a37df9c..dfc0a69 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -142,16 +142,16 @@
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,
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index d093d7c..a0f5c51 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -206,7 +206,7 @@
// 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 @@
#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 @@
fGpu = gpu;
fGpu->ref();
+ fGpu->setContext(this);
fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
fGpu->setClipPathRenderer(fCustomPathRenderer);
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 7973361..bf4b91d 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -492,10 +492,10 @@
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;
}
}
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 31e4d99..06de3ac 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -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 @@
, fCurrPoolStartVertex(0)
, fCurrPoolIndexBuffer(NULL)
, fCurrPoolStartIndex(0)
+ , fContext(NULL)
, fVertexPool(NULL)
, fIndexPool(NULL)
, fQuadIndexBuffer(NULL)
@@ -85,6 +50,7 @@
, fVertexPoolInUse(false)
, fIndexPoolInUse(false)
, fResourceHead(NULL) {
+
#if GR_DEBUG
//gr_run_unittests();
#endif
@@ -210,10 +176,17 @@
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 @@
}
////////////////////////////////////////////////////////////////////////////////
-
-GrTexture::~GrTexture() {
- // use this to set a break-point if needed
-// Gr_clz(3);
-}
-
const GrSamplerState GrSamplerState::gClampNoFilter(
GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 1d159e3..e5f9fa2 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -666,7 +666,7 @@
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 @@
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 @@
}
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 @@
// 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 @@
}
}
-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 @@
}
*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 @@
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 @@
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:
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 25414e4..3eedabf 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -87,7 +87,7 @@
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 @@
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;
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 3e6d909..446949f 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -192,7 +192,7 @@
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) {
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index e4d9b3e..37931e3 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -508,7 +508,7 @@
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;
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index a56e511..4deecd4 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -1042,7 +1042,7 @@
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;
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index e2c81c7..09113e0 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -47,7 +47,7 @@
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()) {
diff --git a/gpu/src/GrTexture.cpp b/gpu/src/GrTexture.cpp
new file mode 100644
index 0000000..7c5f87f
--- /dev/null
+++ b/gpu/src/GrTexture.cpp
@@ -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);
+}
diff --git a/gyp/skia.gyp b/gyp/skia.gyp
index 123a34d..bd19c04 100644
--- a/gyp/skia.gyp
+++ b/gyp/skia.gyp
@@ -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',
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 49dac74..10f1bd0 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -129,10 +129,10 @@
* 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());
}
diff --git a/include/gpu/SkGrTexturePixelRef.h b/include/gpu/SkGrTexturePixelRef.h
index a423251..5bc64f5 100644
--- a/include/gpu/SkGrTexturePixelRef.h
+++ b/include/gpu/SkGrTexturePixelRef.h
@@ -47,5 +47,31 @@
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
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index c525a5d..e58fa26 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -766,17 +766,12 @@
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);
}
}
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index a9b9c99..c19e84d 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -869,10 +869,7 @@
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());
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index ce48be6..76777f0 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -171,11 +171,15 @@
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 @@
}
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 @@
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 @@
GrGpu::kNone_AALevel,
dstM.fBounds.width(),
dstM.fBounds.height(),
- GrTexture::kAlpha_8_PixelConfig
+ kAlpha_8_GrPixelConfig
};
GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 630c3f4..e7e2365 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -213,25 +213,25 @@
///////////////////////////////////////////////////////////////////////////////
-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;
}
}
diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp
index de19f1d..2b173f1 100644
--- a/src/gpu/SkGrTexturePixelRef.cpp
+++ b/src/gpu/SkGrTexturePixelRef.cpp
@@ -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 @@
}
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;
+ }
+}
\ No newline at end of file