Add APIs and plumbing for external rendertaret-textures w/ and w/out MSAA.

Review URL: http://codereview.appspot.com/4388049/



git-svn-id: http://skia.googlecode.com/svn/trunk@1102 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-04-11 17:58:48 +00:00
parent afac88855a
commit 5877ffd5ea
12 changed files with 494 additions and 106 deletions

View File

@ -158,6 +158,43 @@ public:
// Render targets // Render targets
/** /**
* Sets the render target.
* @param target the render target to set. (should not be NULL.)
*/
void setRenderTarget(GrRenderTarget* target);
/**
* Gets the current render target.
* @return the currently bound render target. Should never be NULL.
*/
const GrRenderTarget* getRenderTarget() const;
GrRenderTarget* getRenderTarget();
///////////////////////////////////////////////////////////////////////////
// Platform Surfaces
// GrContext provides an interface for wrapping externally created textures
// and rendertargets in their Gr-equivalents.
/**
* Wraps an existing 3D API surface in a GrObject. desc.fFlags determines
* the type of object returned. If kIsTexture is set the returned object
* will be a GrTexture*. Otherwise, it will be a GrRenderTarget*. If both
* are set the render target object is accessible by
* GrTexture::asRenderTarget().
*
* GL: if the object is a texture Gr may change its GL texture parameters
* when it is drawn.
*
* @param desc description of the object to create.
* @return either a GrTexture* or GrRenderTarget* depending on desc. NULL
* on failure.
*/
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
/**
* DEPRECATED, WILL BE REMOVED SOON. USE createPlatformSurface.
*
* Wraps an externally-created rendertarget in a GrRenderTarget. * Wraps an externally-created rendertarget in a GrRenderTarget.
* @param platformRenderTarget 3D API-specific render target identifier * @param platformRenderTarget 3D API-specific render target identifier
* e.g. in GL platforamRenderTarget is an FBO * e.g. in GL platforamRenderTarget is an FBO
@ -172,9 +209,18 @@ public:
GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget, GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
int stencilBits, int stencilBits,
bool isMultisampled, bool isMultisampled,
int width, int height); int width, int height) {
#if GR_DEBUG
GrPrintf("Using deprecated createPlatformRenderTarget API.");
#endif
return fGpu->createPlatformRenderTarget(platformRenderTarget,
stencilBits, isMultisampled,
width, height);
}
/** /**
* DEPRECATED, WILL BE REMOVED SOON. USE createPlatformSurface.
*
* Reads the current target object (e.g. FBO or IDirect3DSurface9*) and * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
* viewport state from the underlying 3D API and wraps it in a * viewport state from the underlying 3D API and wraps it in a
* GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the * GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the
@ -184,22 +230,12 @@ public:
* @return the newly created GrRenderTarget * @return the newly created GrRenderTarget
*/ */
GrRenderTarget* createRenderTargetFrom3DApiState() { GrRenderTarget* createRenderTargetFrom3DApiState() {
#if GR_DEBUG
GrPrintf("Using deprecated createRenderTargetFrom3DApiState API.");
#endif
return fGpu->createRenderTargetFrom3DApiState(); return fGpu->createRenderTargetFrom3DApiState();
} }
/**
* Sets the render target.
* @param target the render target to set. (should not be NULL.)
*/
void setRenderTarget(GrRenderTarget* target);
/**
* Gets the current render target.
* @return the currently bound render target. Should never be NULL.
*/
const GrRenderTarget* getRenderTarget() const;
GrRenderTarget* getRenderTarget();
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Matrix state // Matrix state

View File

@ -14,7 +14,6 @@
limitations under the License. limitations under the License.
*/ */
#ifndef GrGLTexture_DEFINED #ifndef GrGLTexture_DEFINED
#define GrGLTexture_DEFINED #define GrGLTexture_DEFINED
@ -31,10 +30,10 @@ class GrGLTexture;
class GrGLTexID : public GrRefCnt { class GrGLTexID : public GrRefCnt {
public: public:
GrGLTexID(GrGLuint texID) : fTexID(texID) {} GrGLTexID(GrGLuint texID, bool ownsID) : fTexID(texID), fOwnsID(ownsID) {}
virtual ~GrGLTexID() { virtual ~GrGLTexID() {
if (0 != fTexID) { if (0 != fTexID && fOwnsID) {
GR_GL(DeleteTextures(1, &fTexID)); GR_GL(DeleteTextures(1, &fTexID));
} }
} }
@ -44,27 +43,25 @@ public:
private: private:
GrGLuint fTexID; GrGLuint fTexID;
bool fOwnsID;
}; };
////////////////////////////////////////////////////////////////////////////////
class GrGLRenderTarget : public GrRenderTarget { class GrGLRenderTarget : public GrRenderTarget {
public: public:
virtual ~GrGLRenderTarget() { this->release(); } // set fTexFBOID to this value to indicate that it is multisampled but
// Gr doesn't know how to resolve it.
enum { kUnresolvableFBOID = 0 };
bool resolveable() const { return fRTFBOID != fTexFBOID; }
bool needsResolve() const { return fNeedsResolve; }
void setDirty(bool dirty) { fNeedsResolve = resolveable() && dirty; }
GrGLuint renderFBOID() const { return fRTFBOID; }
GrGLuint textureFBOID() const { return fTexFBOID; }
protected:
struct GLRenderTargetIDs { struct GLRenderTargetIDs {
GrGLuint fRTFBOID; GrGLuint fRTFBOID;
GrGLuint fTexFBOID; GrGLuint fTexFBOID;
GrGLuint fStencilRenderbufferID; GrGLuint fStencilRenderbufferID;
GrGLuint fMSColorRenderbufferID; GrGLuint fMSColorRenderbufferID;
bool fOwnIDs; bool fOwnIDs;
void reset() { memset(this, 0, sizeof(GLRenderTargetIDs)); }
}; };
GrGLRenderTarget(GrGpuGL* gpu, GrGLRenderTarget(GrGpuGL* gpu,
@ -75,10 +72,33 @@ protected:
const GrGLIRect& fViewport, const GrGLIRect& fViewport,
GrGLTexture* texture); GrGLTexture* texture);
virtual ~GrGLRenderTarget() { this->release(); }
void setViewport(const GrGLIRect& rect) { fViewport = rect; } void setViewport(const GrGLIRect& rect) { fViewport = rect; }
const GrGLIRect& getViewport() const { return fViewport; } const GrGLIRect& getViewport() const { return fViewport; }
// overloads of GrResource // The following two functions return the same ID when a
// texture-rendertarget is multisampled, and different IDs when
// it is.
// FBO ID used to render into
GrGLuint renderFBOID() const { return fRTFBOID; }
// FBO ID that has texture ID attached.
GrGLuint textureFBOID() const { return fTexFBOID; }
// override of GrRenderTarget
virtual ResolveType getResolveType() const {
if (fRTFBOID == fTexFBOID) {
// catches FBO 0 and non MSAA case
return kAutoResolves_ResolveType;
} else if (kUnresolvableFBOID == fTexFBOID) {
return kCantResolve_ResolveType;
} else {
return kCanResolve_ResolveType;
}
}
protected:
// override of GrResource
virtual void onAbandon(); virtual void onAbandon();
virtual void onRelease(); virtual void onRelease();
@ -92,10 +112,6 @@ private:
// else own them. // else own them.
bool fOwnIDs; bool fOwnIDs;
// If there separate Texture and RenderTarget FBO IDs then the rendertarget
// must be resolved to the texture FBO before it is used as a texture.
bool fNeedsResolve;
// when we switch to this rendertarget we want to set the viewport to // when we switch to this rendertarget we want to set the viewport to
// only render to to content area (as opposed to the whole allocation) and // only render to to content area (as opposed to the whole allocation) and
// we want the rendering to be at top left (GL has origin in bottom left) // we want the rendering to be at top left (GL has origin in bottom left)
@ -104,12 +120,11 @@ private:
// non-NULL if this RT was created by Gr with an associated GrGLTexture. // non-NULL if this RT was created by Gr with an associated GrGLTexture.
GrGLTexID* fTexIDObj; GrGLTexID* fTexIDObj;
friend class GrGpuGL;
friend class GrGLTexture;
typedef GrRenderTarget INHERITED; typedef GrRenderTarget INHERITED;
}; };
////////////////////////////////////////////////////////////////////////////////
class GrGLTexture : public GrTexture { class GrGLTexture : public GrTexture {
public: public:
@ -122,8 +137,31 @@ public:
GrGLenum fFilter; GrGLenum fFilter;
GrGLenum fWrapS; GrGLenum fWrapS;
GrGLenum fWrapT; GrGLenum fWrapT;
void invalidate() { memset(this, 0xff, sizeof(TexParams)); }
}; };
struct GLTextureDesc {
uint32_t fContentWidth;
uint32_t fContentHeight;
uint32_t fAllocWidth;
uint32_t fAllocHeight;
GrPixelConfig fFormat;
GrGLuint fTextureID;
bool fOwnsID;
GrGLenum fUploadFormat;
GrGLenum fUploadByteCount;
GrGLenum fUploadType;
GrGLuint fStencilBits;
Orientation fOrientation;
};
typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs;
GrGLTexture(GrGpuGL* gpu,
const GLTextureDesc& textureDesc,
const GLRenderTargetIDs& rtIDs,
const TexParams& initialTexParams);
virtual ~GrGLTexture() { this->release(); } virtual ~GrGLTexture() { this->release(); }
// overrides of GrTexture // overrides of GrTexture
@ -176,26 +214,9 @@ public:
// and it is up to the GrGpuGL derivative to handle y-mirroing. // and it is up to the GrGpuGL derivative to handle y-mirroing.
Orientation orientation() const { return fOrientation; } Orientation orientation() const { return fOrientation; }
protected: static const GrGLenum* WrapMode2GLWrap();
struct GLTextureDesc { protected:
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,
const GLTextureDesc& textureDesc,
const GLRenderTargetIDs& rtIDs,
const TexParams& initialTexParams);
// overrides of GrTexture // overrides of GrTexture
virtual void onAbandon(); virtual void onAbandon();
@ -215,10 +236,6 @@ private:
Orientation fOrientation; Orientation fOrientation;
GrGpuGL* fGpuGL; GrGpuGL* fGpuGL;
static const GrGLenum* WrapMode2GLWrap();
friend class GrGpuGL;
typedef GrTexture INHERITED; typedef GrTexture INHERITED;
}; };

View File

@ -192,12 +192,13 @@ public:
* @param width width of the render target * @param width width of the render target
* @param height height of the render target * @param height height of the render target
*/ */
virtual GrRenderTarget* createPlatformRenderTarget( GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
intptr_t platformRenderTarget,
int stencilBits, int stencilBits,
bool isMultisampled, bool isMultisampled,
int width, int height); int width, int height);
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
/** /**
* Reads the current target object (e.g. FBO or IDirect3DSurface9*) and * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
* viewport state from the underlying 3D API and wraps it in a * viewport state from the underlying 3D API and wraps it in a
@ -485,6 +486,7 @@ protected:
virtual GrTexture* createTextureHelper(const TextureDesc& desc, virtual GrTexture* createTextureHelper(const TextureDesc& desc,
const void* srcData, const void* srcData,
size_t rowBytes) = 0; size_t rowBytes) = 0;
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) = 0;
virtual GrRenderTarget* createPlatformRenderTargetHelper( virtual GrRenderTarget* createPlatformRenderTargetHelper(
intptr_t platformRenderTarget, intptr_t platformRenderTarget,
int stencilBits, int stencilBits,
@ -514,8 +516,9 @@ protected:
virtual void forceRenderTargetFlushHelper() = 0; virtual void forceRenderTargetFlushHelper() = 0;
// overridden by API-specific derived class to perform the read pixels. // overridden by API-specific derived class to perform the read pixels.
virtual bool readPixelsHelper(int left, int top, int width, int height, virtual bool onReadPixels(GrRenderTarget* target,
GrPixelConfig, void* buffer) = 0; int left, int top, int width, int height,
GrPixelConfig, void* buffer) = 0;
// called to program the vertex data, indexCount will be 0 if drawing non- // called to program the vertex data, indexCount will be 0 if drawing non-
// indexed geometry. The subclass may adjust the startVertex and/or // indexed geometry. The subclass may adjust the startVertex and/or

View File

@ -58,6 +58,29 @@ public:
*/ */
bool isMultisampled() { return fIsMultisampled; } bool isMultisampled() { return fIsMultisampled; }
/**
* Call to indicate the multisample contents were modified such that the
* render target needs to be resolved before it can be used as texture. Gr
* tracks this for its own drawing and thus this only needs to be called
* when the render target has been modified outside of Gr. Only meaningful
* for Gr-created RT/Textures and Platform RT/Textures created with the
* kGrCanResolve flag.
*/
void flagAsNeedingResolve() {
fNeedsResolve = kCanResolve_ResolveType == getResolveType();
}
/**
* Call to indicate that GrRenderTarget was externally resolved. This may
* allow Gr to skip a redundant resolve step.
*/
void flagAsResolved() { fNeedsResolve = false; }
/**
* @return true if the GrRenderTarget requires MSAA resolving
*/
bool needsResolve() { return fNeedsResolve; }
/** /**
* Reads a rectangle of pixels from the render target. * Reads a rectangle of pixels from the render target.
* @param left left edge of the rectangle to read (inclusive) * @param left left edge of the rectangle to read (inclusive)
@ -73,6 +96,16 @@ public:
bool readPixels(int left, int top, int width, int height, bool readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer); GrPixelConfig config, void* buffer);
// a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO
// 0 in GL), or be unresolvable because the client didn't give us the
// resolve destination.
enum ResolveType {
kCanResolve_ResolveType,
kAutoResolves_ResolveType,
kCantResolve_ResolveType,
};
virtual ResolveType getResolveType() const = 0;
protected: protected:
GrRenderTarget(GrGpu* gpu, GrRenderTarget(GrGpu* gpu,
GrTexture* texture, GrTexture* texture,
@ -86,6 +119,7 @@ protected:
, fHeight(height) , fHeight(height)
, fStencilBits(stencilBits) , fStencilBits(stencilBits)
, fIsMultisampled(isMultisampled) , fIsMultisampled(isMultisampled)
, fNeedsResolve(false)
{} {}
friend class GrTexture; friend class GrTexture;
@ -104,6 +138,7 @@ protected:
int fHeight; int fHeight;
int fStencilBits; int fStencilBits;
bool fIsMultisampled; bool fIsMultisampled;
bool fNeedsResolve;
private: private:
// GrGpu keeps a cached clip in the render target to avoid redundantly // GrGpu keeps a cached clip in the render target to avoid redundantly

View File

@ -154,6 +154,50 @@ template <typename Dst, typename Src> Dst GrTCast(Src src) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// saves value of T* in and restores in destructor
// e.g.:
// {
// GrAutoTPtrValueRestore<int*> autoCountRestore;
// if (useExtra) {
// autoCountRestore.save(&fCount);
// fCount += fExtraCount;
// }
// ...
// } // fCount is restored
//
template <typename T>
class GrAutoTPtrValueRestore {
public:
GrAutoTPtrValueRestore() : fPtr(NULL), fVal() {}
GrAutoTPtrValueRestore(T* ptr) {
fPtr = ptr;
if (NULL != ptr) {
fVal = *ptr;
}
}
~GrAutoTPtrValueRestore() {
if (NULL != fPtr) {
*fPtr = fVal;
}
}
// restores previously saved value (if any) and saves value for passed T*
void save(T* ptr) {
if (NULL != fPtr) {
*fPtr = fVal;
}
fPtr = ptr;
fVal = *ptr;
}
private:
T* fPtr;
T fVal;
};
///////////////////////////////////////////////////////////////////////////////
/** /**
* Type used to describe format of vertices in arrays * Type used to describe format of vertices in arrays
* Values are defined in GrDrawTarget * Values are defined in GrDrawTarget
@ -388,6 +432,139 @@ enum GrConvexHint {
// concave // concave
}; };
///////////////////////////////////////////////////////////////////////////////
enum GrPlatformSurfaceType {
/**
* Specifies that the object being created is a render target.
*/
kRenderTarget_GrPlatformSurfaceType,
/**
* Specifies that the object being created is a texture.
*/
kTexture_GrPlatformSurfaceType,
/**
* Specifies that the object being created is a texture and a render
* target.
*/
kTextureRenderTarget_GrPlatformSurfaceType,
};
enum GrPlatformRenderTargetFlags {
kNone_GrPlatformRenderTargetFlagBit = 0x0,
/**
* Specifies that the object being created is multisampled.
*/
kIsMultisampled_GrPlatformRenderTargetFlagBit = 0x1,
/**
* Gives permission to Gr to perform the downsample-resolve of a
* multisampled render target. If this is not set then read pixel
* operations may fail. If the object is both a texture and render target
* then this *must* be set. Otherwise, if the client wants do its own
* resolves it must create separate GrRenderTarget and GrTexture objects
* and insert appropriate flushes and resolves betweeen data hazards.
* GrRenderTarget has a flagForResolve()
*/
kGrCanResolve_GrPlatformRenderTargetFlagBit = 0x2,
};
static inline GrPlatformRenderTargetFlags operator | (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) {
return (GrPlatformRenderTargetFlags) (+a | +b);
}
static inline GrPlatformRenderTargetFlags operator & (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) {
return (GrPlatformRenderTargetFlags) (+a & +b);
}
// opaque type for 3D API object handles
typedef intptr_t GrPlatform3DObject;
/**
* Description of platform surface to create. See below for GL example.
*/
struct GrPlatformSurfaceDesc {
GrPlatformSurfaceType fSurfaceType; // type of surface to create
/**
* Flags for kRenderTarget and kTextureRenderTarget surface types
*/
GrPlatformRenderTargetFlags fRenderTargetFlags;
int fWidth; // width in pixels
int fHeight; // height in pixels
GrPixelConfig fConfig; // color format
/**
* Number of per sample stencil buffer. Only relevant if kIsRenderTarget is
* set in fFlags.
*/
int fStencilBits;
/**
* Texture object in 3D API. Only relevant if fSurfaceType is kTexture or
* kTextureRenderTarget.
* GL: this is a texture object (glGenTextures)
*/
GrPlatform3DObject fPlatformTexture;
/**
* Render target object in 3D API. Only relevant if fSurfaceType is
* kRenderTarget or kTextureRenderTarget
* GL: this is a FBO object (glGenFramebuffers)
*/
GrPlatform3DObject fPlatformRenderTarget;
/**
* 3D API object used as destination of resolve. Only relevant if
* fSurfaceType is kRenderTarget or kTextureRenderTarget and
* kGrCanResolve is set in fRenderTargetFlags.
* fFlags.
* GL: this is a FBO object (glGenFramebuffers)
*/
GrPlatform3DObject fPlatformResolveDestination;
void reset() { memset(this, 0, sizeof(GrPlatformSurfaceDesc)); }
};
/**
* Example of how to wrap render-to-texture-with-MSAA GL objects with a GrPlatformSurace
*
* GLint colorBufferID;
* glGenRenderbuffers(1, &colorID);
* glBindRenderbuffer(GL_RENDERBUFFER, colorBufferID);
* glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_RGBA, W, H);
*
* GLint stencilBufferID;
* glGenRenderBuffers(1, &stencilBufferID);
* glBindRenderbuffer(GL_RENDERBUFFER, stencilBufferID);
* glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_STENCIL_INDEX8, W, H);
*
* GLint drawFBOID;
* glGenFramebuffers(1, &drawFBOID);
* glBindFramebuffer(GL_FRAMEBUFFER, drawFBOID);
* glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferID);
* glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilBufferID);
*
* GLint textureID;
* glGenTextures(1, &textureID);
* glBindTexture(GL_TEXTURE_2D, textureID);
* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, H, ...);
*
* GLint readFBOID;
* glGenFramebuffers(1, &readFBOID);
* glBindFramebuffer(GL_FRAMEBUFFER, readFBOID);
* glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0);
*
* GrPlatformSurfaceDesc renderTargetTextureDesc;
* renderTargetTextureDesc.fSurfaceType = kTextureRenderTarget_GrPlatformSurfaceType;
* renderTargetTextureDesc.fRenderTargetFlags = (kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit);
* renderTargetTextureDesc.fWidth = W;
* renderTargetTextureDesc.fHeight = H;
* renderTargetTextureDesc.fConfig = kRGBA_8888_GrPixelConfig
* renderTargetTextureDesc.fStencilBits = 8;
* renderTargetTextureDesc.fPlatformTexture = textureID;
* renderTargetTextureDesc.fPlatformRenderTarget = drawFBOID;
* renderTargetTextureDesc.fPlatformResolveDestination = readFBOID;
*
* GrTexture* texture = static_cast<GrTexture*>(grContext->createPlatrformSurface(renderTargetTextureDesc));
*/
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// this is included only to make it easy to use this debugging facility // this is included only to make it easy to use this debugging facility

View File

@ -267,16 +267,26 @@ int GrContext::getMaxTextureDimension() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
GrRenderTarget* GrContext::createPlatformRenderTarget( GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
intptr_t platformRenderTarget, // validate flags here so that GrGpu subclasses don't have to check
int stencilBits, if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
bool isMultisampled, 0 != desc.fRenderTargetFlags) {
int width, int height) { return NULL;
return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits, }
isMultisampled, if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
width, height); (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
}
if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
!(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
}
return fGpu->createPlatformSurface(desc);
} }
///////////////////////////////////////////////////////////////////////////////
bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler, bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
int width, int height) { int width, int height) {
if (!fGpu->supports8BitPalette()) { if (!fGpu->supports8BitPalette()) {

View File

@ -108,7 +108,8 @@ GrGLTexture::GrGLTexture(GrGpuGL* gpu,
textureDesc.fFormat) { textureDesc.fFormat) {
fTexParams = initialTexParams; fTexParams = initialTexParams;
fTexIDObj = new GrGLTexID(textureDesc.fTextureID); fTexIDObj = new GrGLTexID(textureDesc.fTextureID,
textureDesc.fOwnsID);
fUploadFormat = textureDesc.fUploadFormat; fUploadFormat = textureDesc.fUploadFormat;
fUploadByteCount = textureDesc.fUploadByteCount; fUploadByteCount = textureDesc.fUploadByteCount;
fUploadType = textureDesc.fUploadType; fUploadType = textureDesc.fUploadType;

View File

@ -158,6 +158,11 @@ GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
return this->createRenderTargetFrom3DApiStateHelper(); return this->createRenderTargetFrom3DApiStateHelper();
} }
GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
this->handleDirtyContext();
return this->onCreatePlatformSurface(desc);
}
GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) { GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
this->handleDirtyContext(); this->handleDirtyContext();
return this->createVertexBufferHelper(size, dynamic); return this->createVertexBufferHelper(size, dynamic);
@ -183,12 +188,7 @@ bool GrGpu::readPixels(GrRenderTarget* target,
GrPixelConfig config, void* buffer) { GrPixelConfig config, void* buffer) {
this->handleDirtyContext(); this->handleDirtyContext();
GrRenderTarget* prevTarget = fCurrDrawState.fRenderTarget; return this->onReadPixels(target, left, top, width, height, config, buffer);
if (NULL != target) {
fCurrDrawState.fRenderTarget = target;
}
return this->readPixelsHelper(left, top, width, height, config, buffer);
fCurrDrawState.fRenderTarget = prevTarget;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -533,6 +533,73 @@ void GrGpuGL::resetContext() {
fHWDrawState.fRenderTarget = NULL; fHWDrawState.fRenderTarget = NULL;
} }
GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
if (isRenderTarget) {
rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
} else {
GrAssert(!isTexture); // this should have been filtered by GrContext
rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
}
} else {
rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
}
// we don't know what the RB ids are without glGets and we don't care
// since we aren't responsible for deleting them.
rtIDs.fStencilRenderbufferID = 0;
rtIDs.fMSColorRenderbufferID = 0;
rtIDs.fOwnIDs = false;
} else {
rtIDs.reset();
}
if (isTexture) {
GrGLTexture::GLTextureDesc texDesc;
GrGLenum dontCare;
if (!canBeTexture(desc.fConfig, &dontCare,
&texDesc.fUploadFormat,
&texDesc.fUploadType)) {
return NULL;
}
GrGLTexture::TexParams params;
texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
texDesc.fFormat = texDesc.fFormat;
texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
texDesc.fStencilBits = desc.fStencilBits;
texDesc.fTextureID = desc.fPlatformTexture;
texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
texDesc.fOwnsID = false;
params.invalidate(); // rather than do glGets.
return new GrGLTexture(this, texDesc, rtIDs, params);
} else {
GrGLIRect viewport;
viewport.fLeft = 0;
viewport.fBottom = 0;
viewport.fWidth = desc.fWidth;
viewport.fHeight = desc.fHeight;
return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
viewport, NULL);
}
}
GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper( GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
intptr_t platformRenderTarget, intptr_t platformRenderTarget,
int stencilBits, int stencilBits,
@ -655,6 +722,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
glDesc.fAllocHeight = desc.fHeight; glDesc.fAllocHeight = desc.fHeight;
glDesc.fStencilBits = 0; glDesc.fStencilBits = 0;
glDesc.fFormat = desc.fFormat; glDesc.fFormat = desc.fFormat;
glDesc.fOwnsID = true;
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag); bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
if (!canBeTexture(desc.fFormat, if (!canBeTexture(desc.fFormat,
@ -1154,21 +1222,35 @@ void GrGpuGL::forceRenderTargetFlushHelper() {
flushRenderTarget(); flushRenderTarget();
} }
bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height, bool GrGpuGL::onReadPixels(GrRenderTarget* target,
GrPixelConfig config, void* buffer) { int left, int top, int width, int height,
GrPixelConfig config, void* buffer) {
GrGLenum internalFormat; // we don't use this for glReadPixels GrGLenum internalFormat; // we don't use this for glReadPixels
GrGLenum format; GrGLenum format;
GrGLenum type; GrGLenum type;
if (!this->canBeTexture(config, &internalFormat, &format, &type)) { if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
return false; return false;
} }
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
if (NULL == fCurrDrawState.fRenderTarget) { GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
return false; switch (tgt->getResolveType()) {
case GrGLRenderTarget::kCantResolve_ResolveType:
return false;
case GrGLRenderTarget::kAutoResolves_ResolveType:
autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
fCurrDrawState.fRenderTarget = target;
flushRenderTarget();
break;
case GrGLRenderTarget::kCanResolve_ResolveType:
resolveRenderTarget(tgt);
// we don't track the state of the READ FBO ID.
GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
break;
default:
GrCrash("Unknown resolve type");
} }
flushRenderTarget();
const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport(); const GrGLIRect& glvp = tgt->getViewport();
// the read rect is viewport-relative // the read rect is viewport-relative
GrGLIRect readRect; GrGLIRect readRect;
@ -1208,7 +1290,7 @@ void GrGpuGL::flushRenderTarget() {
#if GR_COLLECT_STATS #if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt; ++fStats.fRenderTargetChngCnt;
#endif #endif
rt->setDirty(true); rt->flagAsNeedingResolve();
#if GR_DEBUG #if GR_DEBUG
GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) { if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
@ -1316,10 +1398,9 @@ void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
#endif #endif
} }
void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) { void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
if (NULL != rt && rt->needsResolve()) { if (rt->needsResolve()) {
GrAssert(kNone_MSFBO != fMSFBOType); GrAssert(kNone_MSFBO != fMSFBOType);
GrAssert(rt->textureFBOID() != rt->renderFBOID()); GrAssert(rt->textureFBOID() != rt->renderFBOID());
GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
@ -1329,32 +1410,32 @@ void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
#if GR_COLLECT_STATS #if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt; ++fStats.fRenderTargetChngCnt;
#endif #endif
// make sure we go through set render target // make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID.
fHWDrawState.fRenderTarget = NULL; fHWDrawState.fRenderTarget = NULL;
const GrGLIRect& vp = rt->getViewport();
GrGLint left = 0;
GrGLint right = texture->width();
// we will have rendered to the top of the FBO.
GrGLint top = texture->allocHeight();
GrGLint bottom = texture->allocHeight() - texture->height();
if (kAppleES_MSFBO == fMSFBOType) { if (kAppleES_MSFBO == fMSFBOType) {
// Apple's extension uses the scissor as the blit bounds. // Apple's extension uses the scissor as the blit bounds.
GR_GL(Enable(GR_GL_SCISSOR_TEST)); GR_GL(Enable(GR_GL_SCISSOR_TEST));
GR_GL(Scissor(left, bottom, right-left, top-bottom)); GR_GL(Scissor(vp.fLeft, vp.fBottom,
vp.fWidth, vp.fHeight));
GR_GL(ResolveMultisampleFramebuffer()); GR_GL(ResolveMultisampleFramebuffer());
fHWBounds.fScissorRect.invalidate(); fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = true; fHWBounds.fScissorEnabled = true;
} else { } else {
if (kDesktopARB_MSFBO != fMSFBOType) { if (kDesktopARB_MSFBO != fMSFBOType) {
// these respect the scissor during the blit, so disable it. // this respects the scissor during the blit, so disable it.
GrAssert(kDesktopEXT_MSFBO == fMSFBOType); GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
flushScissor(NULL); flushScissor(NULL);
} }
GR_GL(BlitFramebuffer(left, bottom, right, top, int right = vp.fLeft + vp.fWidth;
left, bottom, right, top, int top = vp.fBottom + vp.fHeight;
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
vp.fLeft, vp.fBottom, right, top,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
} }
rt->setDirty(false); rt->flagAsResolved();
} }
} }
@ -1631,7 +1712,11 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
// texture and now we're texuring from the rt it will still be // texture and now we're texuring from the rt it will still be
// the last bound texture, but it needs resolving. So keep this // the last bound texture, but it needs resolving. So keep this
// out of the "last != next" check. // out of the "last != next" check.
resolveTextureRenderTarget(nextTexture); GrGLRenderTarget* texRT =
static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
if (NULL != texRT) {
resolveRenderTarget(texRT);
}
if (fHWDrawState.fTextures[s] != nextTexture) { if (fHWDrawState.fTextures[s] != nextTexture) {
setTextureUnit(s); setTextureUnit(s);

View File

@ -79,21 +79,21 @@ protected:
bool dynamic); bool dynamic);
virtual GrIndexBuffer* createIndexBufferHelper(uint32_t size, virtual GrIndexBuffer* createIndexBufferHelper(uint32_t size,
bool dynamic); bool dynamic);
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc);
virtual GrRenderTarget* createPlatformRenderTargetHelper( virtual GrRenderTarget* createPlatformRenderTargetHelper(
intptr_t platformRenderTarget, intptr_t platformRenderTarget,
int stencilBits, int stencilBits,
bool isMultisampled, bool isMultisampled,
int width, int height); int width, int height);
virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper(); virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper();
virtual void eraseColorHelper(GrColor color); virtual void eraseColorHelper(GrColor color);
virtual void forceRenderTargetFlushHelper(); virtual void forceRenderTargetFlushHelper();
virtual bool readPixelsHelper(int left, int top, int width, int height, virtual bool onReadPixels(GrRenderTarget* target,
GrPixelConfig, void* buffer); int left, int top, int width, int height,
GrPixelConfig, void* buffer);
virtual void drawIndexedHelper(GrPrimitiveType type, virtual void drawIndexedHelper(GrPrimitiveType type,
uint32_t startVertex, uint32_t startVertex,
@ -158,7 +158,7 @@ private:
void flushAAState(GrPrimitiveType type); void flushAAState(GrPrimitiveType type);
void flushBlend(GrPrimitiveType type); void flushBlend(GrPrimitiveType type);
void resolveTextureRenderTarget(GrGLTexture* texture); void resolveRenderTarget(GrGLRenderTarget* texture);
bool canBeTexture(GrPixelConfig config, bool canBeTexture(GrPixelConfig config,
GrGLenum* internalFormat, GrGLenum* internalFormat,

View File

@ -35,6 +35,14 @@ public:
*/ */
SkGpuDeviceFactory(GrContext*, GrRenderTarget* rootRenderTarget); SkGpuDeviceFactory(GrContext*, GrRenderTarget* rootRenderTarget);
/**
* When the root layer is both a GrRenderTarget and a GrTexture it
* is handy to have the factory hang on to a ref to the GrTexture object.
* This is because the GrTexture has a ref to the GrRenderTarget but not
* vice-versa.
*/
SkGpuDeviceFactory(GrContext*, GrTexture* rootRenderTargetTexture);
virtual ~SkGpuDeviceFactory(); virtual ~SkGpuDeviceFactory();
virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width, virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
@ -43,6 +51,7 @@ public:
private: private:
GrContext* fContext; GrContext* fContext;
GrRenderTarget* fRootRenderTarget; GrRenderTarget* fRootRenderTarget;
GrTexture* fRootTexture;
}; };
#endif #endif

View File

@ -1453,12 +1453,27 @@ SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
rootRenderTarget->ref(); rootRenderTarget->ref();
} }
context->ref(); context->ref();
fRootTexture = NULL;
}
SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) {
GrAssert(NULL != context);
GrAssert(NULL != rootRenderTargetTexture);
GrAssert(NULL != rootRenderTargetTexture->asRenderTarget());
fRootTexture = rootRenderTargetTexture;
rootRenderTargetTexture->ref();
fRootRenderTarget = rootRenderTargetTexture->asRenderTarget();
fRootRenderTarget->ref();
context->ref();
} }
SkGpuDeviceFactory::~SkGpuDeviceFactory() { SkGpuDeviceFactory::~SkGpuDeviceFactory() {
fContext->unref(); fContext->unref();
fRootRenderTarget->unref(); fRootRenderTarget->unref();
GrSafeUnref(fRootTexture);
} }
SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,