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:
parent
afac88855a
commit
5877ffd5ea
@ -158,6 +158,43 @@ public:
|
||||
// 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.
|
||||
* @param platformRenderTarget 3D API-specific render target identifier
|
||||
* e.g. in GL platforamRenderTarget is an FBO
|
||||
@ -172,9 +209,18 @@ public:
|
||||
GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
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
|
||||
* viewport state from the underlying 3D API and wraps it in a
|
||||
* GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the
|
||||
@ -184,22 +230,12 @@ public:
|
||||
* @return the newly created GrRenderTarget
|
||||
*/
|
||||
GrRenderTarget* createRenderTargetFrom3DApiState() {
|
||||
#if GR_DEBUG
|
||||
GrPrintf("Using deprecated createRenderTargetFrom3DApiState API.");
|
||||
#endif
|
||||
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
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GrGLTexture_DEFINED
|
||||
#define GrGLTexture_DEFINED
|
||||
|
||||
@ -31,10 +30,10 @@ class GrGLTexture;
|
||||
class GrGLTexID : public GrRefCnt {
|
||||
|
||||
public:
|
||||
GrGLTexID(GrGLuint texID) : fTexID(texID) {}
|
||||
GrGLTexID(GrGLuint texID, bool ownsID) : fTexID(texID), fOwnsID(ownsID) {}
|
||||
|
||||
virtual ~GrGLTexID() {
|
||||
if (0 != fTexID) {
|
||||
if (0 != fTexID && fOwnsID) {
|
||||
GR_GL(DeleteTextures(1, &fTexID));
|
||||
}
|
||||
}
|
||||
@ -44,27 +43,25 @@ public:
|
||||
|
||||
private:
|
||||
GrGLuint fTexID;
|
||||
bool fOwnsID;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrGLRenderTarget : public GrRenderTarget {
|
||||
|
||||
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 {
|
||||
GrGLuint fRTFBOID;
|
||||
GrGLuint fTexFBOID;
|
||||
GrGLuint fStencilRenderbufferID;
|
||||
GrGLuint fMSColorRenderbufferID;
|
||||
bool fOwnIDs;
|
||||
void reset() { memset(this, 0, sizeof(GLRenderTargetIDs)); }
|
||||
};
|
||||
|
||||
GrGLRenderTarget(GrGpuGL* gpu,
|
||||
@ -75,10 +72,33 @@ protected:
|
||||
const GrGLIRect& fViewport,
|
||||
GrGLTexture* texture);
|
||||
|
||||
virtual ~GrGLRenderTarget() { this->release(); }
|
||||
|
||||
void setViewport(const GrGLIRect& rect) { fViewport = rect; }
|
||||
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 onRelease();
|
||||
|
||||
@ -92,10 +112,6 @@ private:
|
||||
// else own them.
|
||||
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
|
||||
// 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)
|
||||
@ -104,12 +120,11 @@ private:
|
||||
// non-NULL if this RT was created by Gr with an associated GrGLTexture.
|
||||
GrGLTexID* fTexIDObj;
|
||||
|
||||
friend class GrGpuGL;
|
||||
friend class GrGLTexture;
|
||||
|
||||
typedef GrRenderTarget INHERITED;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrGLTexture : public GrTexture {
|
||||
|
||||
public:
|
||||
@ -122,8 +137,31 @@ public:
|
||||
GrGLenum fFilter;
|
||||
GrGLenum fWrapS;
|
||||
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(); }
|
||||
|
||||
// overrides of GrTexture
|
||||
@ -176,26 +214,9 @@ public:
|
||||
// and it is up to the GrGpuGL derivative to handle y-mirroing.
|
||||
Orientation orientation() const { return fOrientation; }
|
||||
|
||||
protected:
|
||||
static const GrGLenum* WrapMode2GLWrap();
|
||||
|
||||
struct GLTextureDesc {
|
||||
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);
|
||||
protected:
|
||||
|
||||
// overrides of GrTexture
|
||||
virtual void onAbandon();
|
||||
@ -215,10 +236,6 @@ private:
|
||||
Orientation fOrientation;
|
||||
GrGpuGL* fGpuGL;
|
||||
|
||||
static const GrGLenum* WrapMode2GLWrap();
|
||||
|
||||
friend class GrGpuGL;
|
||||
|
||||
typedef GrTexture INHERITED;
|
||||
};
|
||||
|
||||
|
@ -192,12 +192,13 @@ public:
|
||||
* @param width width of the render target
|
||||
* @param height height of the render target
|
||||
*/
|
||||
virtual GrRenderTarget* createPlatformRenderTarget(
|
||||
intptr_t platformRenderTarget,
|
||||
GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
bool isMultisampled,
|
||||
int width, int height);
|
||||
|
||||
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
|
||||
|
||||
/**
|
||||
* Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
|
||||
* viewport state from the underlying 3D API and wraps it in a
|
||||
@ -485,6 +486,7 @@ protected:
|
||||
virtual GrTexture* createTextureHelper(const TextureDesc& desc,
|
||||
const void* srcData,
|
||||
size_t rowBytes) = 0;
|
||||
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) = 0;
|
||||
virtual GrRenderTarget* createPlatformRenderTargetHelper(
|
||||
intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
@ -514,8 +516,9 @@ protected:
|
||||
virtual void forceRenderTargetFlushHelper() = 0;
|
||||
|
||||
// overridden by API-specific derived class to perform the read pixels.
|
||||
virtual bool readPixelsHelper(int left, int top, int width, int height,
|
||||
GrPixelConfig, void* buffer) = 0;
|
||||
virtual bool onReadPixels(GrRenderTarget* target,
|
||||
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-
|
||||
// indexed geometry. The subclass may adjust the startVertex and/or
|
||||
|
@ -58,6 +58,29 @@ public:
|
||||
*/
|
||||
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.
|
||||
* @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,
|
||||
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:
|
||||
GrRenderTarget(GrGpu* gpu,
|
||||
GrTexture* texture,
|
||||
@ -86,6 +119,7 @@ protected:
|
||||
, fHeight(height)
|
||||
, fStencilBits(stencilBits)
|
||||
, fIsMultisampled(isMultisampled)
|
||||
, fNeedsResolve(false)
|
||||
{}
|
||||
|
||||
friend class GrTexture;
|
||||
@ -104,6 +138,7 @@ protected:
|
||||
int fHeight;
|
||||
int fStencilBits;
|
||||
bool fIsMultisampled;
|
||||
bool fNeedsResolve;
|
||||
|
||||
private:
|
||||
// GrGpu keeps a cached clip in the render target to avoid redundantly
|
||||
|
@ -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
|
||||
* Values are defined in GrDrawTarget
|
||||
@ -388,6 +432,139 @@ enum GrConvexHint {
|
||||
// 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
|
||||
|
@ -267,16 +267,26 @@ int GrContext::getMaxTextureDimension() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrRenderTarget* GrContext::createPlatformRenderTarget(
|
||||
intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
bool isMultisampled,
|
||||
int width, int height) {
|
||||
return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,
|
||||
isMultisampled,
|
||||
width, height);
|
||||
GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
|
||||
// validate flags here so that GrGpu subclasses don't have to check
|
||||
if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
|
||||
0 != desc.fRenderTargetFlags) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
|
||||
(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,
|
||||
int width, int height) {
|
||||
if (!fGpu->supports8BitPalette()) {
|
||||
|
@ -108,7 +108,8 @@ GrGLTexture::GrGLTexture(GrGpuGL* gpu,
|
||||
textureDesc.fFormat) {
|
||||
|
||||
fTexParams = initialTexParams;
|
||||
fTexIDObj = new GrGLTexID(textureDesc.fTextureID);
|
||||
fTexIDObj = new GrGLTexID(textureDesc.fTextureID,
|
||||
textureDesc.fOwnsID);
|
||||
fUploadFormat = textureDesc.fUploadFormat;
|
||||
fUploadByteCount = textureDesc.fUploadByteCount;
|
||||
fUploadType = textureDesc.fUploadType;
|
||||
|
@ -158,6 +158,11 @@ GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
|
||||
return this->createRenderTargetFrom3DApiStateHelper();
|
||||
}
|
||||
|
||||
GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
|
||||
this->handleDirtyContext();
|
||||
return this->onCreatePlatformSurface(desc);
|
||||
}
|
||||
|
||||
GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
|
||||
this->handleDirtyContext();
|
||||
return this->createVertexBufferHelper(size, dynamic);
|
||||
@ -183,12 +188,7 @@ bool GrGpu::readPixels(GrRenderTarget* target,
|
||||
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;
|
||||
return this->onReadPixels(target, left, top, width, height, config, buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -533,6 +533,73 @@ void GrGpuGL::resetContext() {
|
||||
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(
|
||||
intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
@ -655,6 +722,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
|
||||
glDesc.fAllocHeight = desc.fHeight;
|
||||
glDesc.fStencilBits = 0;
|
||||
glDesc.fFormat = desc.fFormat;
|
||||
glDesc.fOwnsID = true;
|
||||
|
||||
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
|
||||
if (!canBeTexture(desc.fFormat,
|
||||
@ -1154,21 +1222,35 @@ void GrGpuGL::forceRenderTargetFlushHelper() {
|
||||
flushRenderTarget();
|
||||
}
|
||||
|
||||
bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer) {
|
||||
bool GrGpuGL::onReadPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer) {
|
||||
GrGLenum internalFormat; // we don't use this for glReadPixels
|
||||
GrGLenum format;
|
||||
GrGLenum type;
|
||||
if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
|
||||
return false;
|
||||
}
|
||||
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
|
||||
GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
|
||||
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");
|
||||
}
|
||||
|
||||
if (NULL == fCurrDrawState.fRenderTarget) {
|
||||
return false;
|
||||
}
|
||||
flushRenderTarget();
|
||||
|
||||
const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
|
||||
const GrGLIRect& glvp = tgt->getViewport();
|
||||
|
||||
// the read rect is viewport-relative
|
||||
GrGLIRect readRect;
|
||||
@ -1208,7 +1290,7 @@ void GrGpuGL::flushRenderTarget() {
|
||||
#if GR_COLLECT_STATS
|
||||
++fStats.fRenderTargetChngCnt;
|
||||
#endif
|
||||
rt->setDirty(true);
|
||||
rt->flagAsNeedingResolve();
|
||||
#if GR_DEBUG
|
||||
GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
|
||||
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
|
||||
@ -1316,10 +1398,9 @@ void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
|
||||
#endif
|
||||
}
|
||||
|
||||
void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
|
||||
GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
|
||||
void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
|
||||
|
||||
if (NULL != rt && rt->needsResolve()) {
|
||||
if (rt->needsResolve()) {
|
||||
GrAssert(kNone_MSFBO != fMSFBOType);
|
||||
GrAssert(rt->textureFBOID() != rt->renderFBOID());
|
||||
GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
|
||||
@ -1329,32 +1410,32 @@ void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
|
||||
#if GR_COLLECT_STATS
|
||||
++fStats.fRenderTargetChngCnt;
|
||||
#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;
|
||||
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) {
|
||||
// Apple's extension uses the scissor as the blit bounds.
|
||||
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());
|
||||
fHWBounds.fScissorRect.invalidate();
|
||||
fHWBounds.fScissorEnabled = true;
|
||||
} else {
|
||||
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);
|
||||
flushScissor(NULL);
|
||||
}
|
||||
GR_GL(BlitFramebuffer(left, bottom, right, top,
|
||||
left, bottom, right, top,
|
||||
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
|
||||
int right = vp.fLeft + vp.fWidth;
|
||||
int top = vp.fBottom + vp.fHeight;
|
||||
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
|
||||
// the last bound texture, but it needs resolving. So keep this
|
||||
// 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) {
|
||||
setTextureUnit(s);
|
||||
|
@ -79,21 +79,21 @@ protected:
|
||||
bool dynamic);
|
||||
virtual GrIndexBuffer* createIndexBufferHelper(uint32_t size,
|
||||
bool dynamic);
|
||||
|
||||
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc);
|
||||
virtual GrRenderTarget* createPlatformRenderTargetHelper(
|
||||
intptr_t platformRenderTarget,
|
||||
int stencilBits,
|
||||
bool isMultisampled,
|
||||
int width, int height);
|
||||
|
||||
virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper();
|
||||
|
||||
virtual void eraseColorHelper(GrColor color);
|
||||
|
||||
virtual void forceRenderTargetFlushHelper();
|
||||
|
||||
virtual bool readPixelsHelper(int left, int top, int width, int height,
|
||||
GrPixelConfig, void* buffer);
|
||||
virtual bool onReadPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig, void* buffer);
|
||||
|
||||
virtual void drawIndexedHelper(GrPrimitiveType type,
|
||||
uint32_t startVertex,
|
||||
@ -158,7 +158,7 @@ private:
|
||||
void flushAAState(GrPrimitiveType type);
|
||||
void flushBlend(GrPrimitiveType type);
|
||||
|
||||
void resolveTextureRenderTarget(GrGLTexture* texture);
|
||||
void resolveRenderTarget(GrGLRenderTarget* texture);
|
||||
|
||||
bool canBeTexture(GrPixelConfig config,
|
||||
GrGLenum* internalFormat,
|
||||
|
@ -34,6 +34,14 @@ public:
|
||||
* construction.
|
||||
*/
|
||||
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();
|
||||
|
||||
@ -43,6 +51,7 @@ public:
|
||||
private:
|
||||
GrContext* fContext;
|
||||
GrRenderTarget* fRootRenderTarget;
|
||||
GrTexture* fRootTexture;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1453,12 +1453,27 @@ SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
|
||||
rootRenderTarget->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() {
|
||||
fContext->unref();
|
||||
fRootRenderTarget->unref();
|
||||
GrSafeUnref(fRootTexture);
|
||||
}
|
||||
|
||||
SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
|
||||
|
Loading…
Reference in New Issue
Block a user