| Index: src/gpu/gl/GrGLRenderTarget.h | 
| diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h | 
| index 7e7349257f054ac44e8a32cd5626c1cf94e1041c..485ae4a7919d1d967b8600ac8c8093da80fe4af1 100644 | 
| --- a/src/gpu/gl/GrGLRenderTarget.h | 
| +++ b/src/gpu/gl/GrGLRenderTarget.h | 
| @@ -15,15 +15,59 @@ | 
|  | 
| class GrGLGpu; | 
|  | 
| -class GrGLRenderTarget : public GrRenderTarget { | 
| +/** Represents a GL FBO object. It has a gen ID which is valid whenever the FBO ID owned by the | 
| +    object is valid. The gen IDs are not recycled after FBOs are freed, unlike FBO IDs, and so | 
| +    can be used to uniquely identity FBO ID instantiations. If this object owns an FBO ID, the ID | 
| +    must be deleted or abandoned before this object is freed. FBO IDs should never be owned by | 
| +    more than one instance. */ | 
| +class GrGLFBO : public SkNVRefCnt<GrGLFBO> { | 
| public: | 
| -    // set fTexFBOID to this value to indicate that it is multisampled but | 
| -    // Gr doesn't know how to resolve it. | 
| -    enum { kUnresolvableFBOID = 0 }; | 
| +    SK_DECLARE_INST_COUNT(GrGLFBO); | 
| + | 
| +    /** Initializes to an FBO. The FBO should already be valid in the relevant GL context. */ | 
| +    GrGLFBO(GrGLint id) : fID(id), fIsValid(true) {} | 
| + | 
| +    /** Initializes to an FBO ID generated using the interface. */ | 
| +    GrGLFBO(const GrGLInterface* gl) { | 
| +        GR_GL_CALL(gl, GenFramebuffers(1, &fID)); | 
| +        fIsValid = SkToBool(fID); | 
| +    } | 
| + | 
| +    ~GrGLFBO() { SkASSERT(!this->isValid()); } | 
| + | 
| +    /** Has this object been released or abandoned? */ | 
| +    bool isValid() const { return fIsValid; } | 
| + | 
| +    GrGLint fboID() const { SkASSERT(this->isValid()); return fID; } | 
| + | 
| +    bool isDefaultFramebuffer() const { return fIsValid && 0 == fID; } | 
| + | 
| +    /** Give up ownership of the FBO ID owned by this object without deleting it. */ | 
| +    void abandon(); | 
| + | 
| +    /** Delete and give up ownership of the the FBO ID if it is valid. */ | 
| +    void release(const GrGLInterface*); | 
| + | 
| +private: | 
| +    static uint32_t NextGenID() { | 
| +        static int32_t gGenID = SK_InvalidGenID + 1; | 
| +        return static_cast<uint32_t>(sk_atomic_inc(&gGenID)); | 
| +    } | 
| + | 
| +    GrGLuint    fID; | 
| +    bool        fIsValid; | 
| + | 
| +    typedef SkRefCnt INHERITED; | 
| +}; | 
| + | 
| +////////////////////////////////////////////////////////////////////////////// | 
|  | 
| +/** GL-specific subclass of GrRenderTarget. */ | 
| +class GrGLRenderTarget : public GrRenderTarget { | 
| +public: | 
| struct IDDesc { | 
| -        GrGLuint                    fRTFBOID; | 
| -        GrGLuint                    fTexFBOID; | 
| +        SkAutoTUnref<GrGLFBO>       fRenderFBO; | 
| +        SkAutoTUnref<GrGLFBO>       fTextureFBO; | 
| GrGLuint                    fMSColorRenderbufferID; | 
| GrGpuResource::LifeCycle    fLifeCycle; | 
| }; | 
| @@ -33,21 +77,33 @@ public: | 
| void setViewport(const GrGLIRect& rect) { fViewport = rect; } | 
| const GrGLIRect& getViewport() const { return fViewport; } | 
|  | 
| -    // The following two functions return the same ID when a | 
| -    // texture/render target 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; } | 
| +    // For multisampled renderbuffer render targets, these will return different GrGLFBO objects. If | 
| +    // the render target is not texturable, textureFBO() returns NULL. If the render target auto | 
| +    // resolves to a texture, the same object is returned. | 
| + | 
| +    // FBO that should be rendered into. Always non-NULL unless this resource is destroyed | 
| +    // (this->wasDestroyed()). | 
| +    const GrGLFBO* renderFBO() const { | 
| +        SkASSERT(fRenderFBO && fRenderFBO->isValid()); | 
| +        return fRenderFBO; | 
| +    } | 
| + | 
| +    // FBO that has the target's texture ID attached. The return value may be: | 
| +    //      * NULL when this render target is not a texture, | 
| +    //      * the same as renderFBO() when this surface is not multisampled or auto-resolves, | 
| +    //      * or different than renderFBO() when it requires explicit resolving via | 
| +    //        glBlitFramebuffer. | 
| +    const GrGLFBO* textureFBO() const { | 
| +        SkASSERT(!fTextureFBO || fTextureFBO->isValid()); | 
| +        return fTextureFBO; | 
| +    } | 
|  | 
| // override of GrRenderTarget | 
| ResolveType getResolveType() const SK_OVERRIDE { | 
| -        if (!this->isMultisampled() || | 
| -            fRTFBOID == fTexFBOID) { | 
| +        if (!this->isMultisampled() || this->renderFBO() == this->textureFBO()) { | 
| // catches FBO 0 and non MSAA case | 
| return kAutoResolves_ResolveType; | 
| -        } else if (kUnresolvableFBOID == fTexFBOID) { | 
| +        } else if (!this->textureFBO()) { | 
| return kCantResolve_ResolveType; | 
| } else { | 
| return kCanResolve_ResolveType; | 
| @@ -73,23 +129,23 @@ protected: | 
| size_t onGpuMemorySize() const SK_OVERRIDE; | 
|  | 
| private: | 
| -    GrGLuint      fRTFBOID; | 
| -    GrGLuint      fTexFBOID; | 
| -    GrGLuint      fMSColorRenderbufferID; | 
| +    SkAutoTUnref<GrGLFBO>   fRenderFBO; | 
| +    SkAutoTUnref<GrGLFBO>   fTextureFBO; | 
| +    GrGLuint                fMSColorRenderbufferID; | 
|  | 
| // We track this separately from GrGpuResource because this may be both a texture and a render | 
| // target, and the texture may be wrapped while the render target is not. | 
| -    bool fIsWrapped; | 
| +    bool                    fIsWrapped; | 
|  | 
| // when we switch to this render target we want to set the viewport to | 
| // only render 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) | 
| -    GrGLIRect fViewport; | 
| +    GrGLIRect               fViewport; | 
|  | 
| // onGpuMemorySize() needs to know what how many color values are owned per pixel. However, | 
| // abandon and release zero out the IDs and the cache needs to know the size even after those | 
| // actions. | 
| -    uint8_t fColorValuesPerPixel; | 
| +    uint8_t                 fColorValuesPerPixel; | 
|  | 
| typedef GrRenderTarget INHERITED; | 
| }; | 
|  |