// 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
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
* @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
limitations under the License.
*/
-
#ifndef GrGLTexture_DEFINED
#define GrGLTexture_DEFINED
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));
}
}
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,
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();
// 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)
// 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:
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
// 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();
Orientation fOrientation;
GrGpuGL* fGpuGL;
- static const GrGLenum* WrapMode2GLWrap();
-
- friend class GrGpuGL;
-
typedef GrTexture INHERITED;
};
* @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
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,
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
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)
* @param top top edge of the rectangle to read (inclusive)
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,
, fHeight(height)
, fStencilBits(stencilBits)
, fIsMultisampled(isMultisampled)
+ , fNeedsResolve(false)
{}
friend class GrTexture;
int fHeight;
int fStencilBits;
bool fIsMultisampled;
+ bool fNeedsResolve;
private:
// GrGpu keeps a cached clip in the render target to avoid redundantly
///////////////////////////////////////////////////////////////////////////////
+// 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
///////////////////////////////////////////////////////////////////////////////
+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
#include "GrInstanceCounter.h"
///////////////////////////////////////////////////////////////////////////////
-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()) {
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;
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);
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);
}
////////////////////////////////////////////////////////////////////////////////
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,
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,
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;
#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) {
#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,
#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();
}
}
// 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);
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,
void flushAAState(GrPrimitiveType type);
void flushBlend(GrPrimitiveType type);
- void resolveTextureRenderTarget(GrGLTexture* texture);
+ void resolveRenderTarget(GrGLRenderTarget* texture);
bool canBeTexture(GrPixelConfig config,
GrGLenum* internalFormat,
* 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();
private:
GrContext* fContext;
GrRenderTarget* fRootRenderTarget;
+ GrTexture* fRootTexture;
};
#endif
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,