/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrRenderTarget_DEFINED #define GrRenderTarget_DEFINED #include "GrSurface.h" #include "SkRect.h" class GrCaps; class GrDrawTarget; class GrStencilAttachment; class GrRenderTargetPriv; /** * GrRenderTarget represents a 2D buffer of pixels that can be rendered to. * A context's render target is set by setRenderTarget(). Render targets are * created by a createTexture with the kRenderTarget_SurfaceFlag flag. * Additionally, GrContext provides methods for creating GrRenderTargets * that wrap externally created render targets. */ class GrRenderTarget : virtual public GrSurface { public: // GrSurface overrides GrRenderTarget* asRenderTarget() override { return this; } const GrRenderTarget* asRenderTarget() const override { return this; } // GrRenderTarget /** * On some hardware it is possible for a render target to have multisampling * only in certain buffers. * Enforce only two legal sample configs. * kUnified_SampleConfig signifies multisampling in both color and stencil * buffers and is available across all hardware. * kStencil_SampleConfig means multisampling is present in stencil buffer * only; this config requires hardware support of * NV_framebuffer_mixed_samples. */ enum SampleConfig { kUnified_SampleConfig = 0, kStencil_SampleConfig = 1 }; /** * @return true if the surface is multisampled in all buffers, * false otherwise */ bool isUnifiedMultisampled() const { if (fSampleConfig != kUnified_SampleConfig) { return false; } return 0 != fDesc.fSampleCnt; } /** * @return true if the surface is multisampled in the stencil buffer, * false otherwise */ bool isStencilBufferMultisampled() const { return 0 != fDesc.fSampleCnt; } /** * @return the number of color samples-per-pixel, or zero if non-MSAA or * multisampled in the stencil buffer only. */ int numColorSamples() const { if (fSampleConfig == kUnified_SampleConfig) { return fDesc.fSampleCnt; } return 0; } /** * @return the number of stencil samples-per-pixel, or zero if non-MSAA. */ int numStencilSamples() const { return fDesc.fSampleCnt; } /** * @return true if the surface is mixed sampled, false otherwise. */ bool hasMixedSamples() const { SkASSERT(kStencil_SampleConfig != fSampleConfig || this->isStencilBufferMultisampled()); return kStencil_SampleConfig == fSampleConfig; } /** * 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. This has no * effect on wrapped backend render targets. * * @param rect a rect bounding the area needing resolve. NULL indicates * the whole RT needs resolving. */ void flagAsNeedingResolve(const SkIRect* rect = NULL); /** * Call to override the region that needs to be resolved. */ void overrideResolveRect(const SkIRect rect); /** * Call to indicate that GrRenderTarget was externally resolved. This may * allow Gr to skip a redundant resolve step. */ void flagAsResolved() { fResolveRect.setLargestInverted(); } /** * @return true if the GrRenderTarget requires MSAA resolving */ bool needsResolve() const { return !fResolveRect.isEmpty(); } /** * Returns a rect bounding the region needing resolving. */ const SkIRect& getResolveRect() const { return fResolveRect; } /** * Provide a performance hint that the render target's contents are allowed * to become undefined. */ void discard(); // 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; /** * Return the native ID or handle to the rendertarget, depending on the * platform. e.g. on OpenGL, return the FBO ID. */ virtual GrBackendObject getRenderTargetHandle() const = 0; // Checked when this object is asked to attach a stencil buffer. virtual bool canAttemptStencilAttachment() const = 0; // Provides access to functions that aren't part of the public API. GrRenderTargetPriv renderTargetPriv(); const GrRenderTargetPriv renderTargetPriv() const; void setLastDrawTarget(GrDrawTarget* dt); GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; } static SampleConfig ComputeSampleConfig(const GrCaps& caps, int sampleCnt); protected: GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr) : INHERITED(gpu, desc) , fStencilAttachment(stencil) , fSampleConfig(sampleConfig) , fLastDrawTarget(nullptr) { fResolveRect.setLargestInverted(); } ~GrRenderTarget() override; // override of GrResource void onAbandon() override; void onRelease() override; private: // Allows the backends to perform any additional work that is required for attaching a // GrStencilAttachment. When this is called, the GrStencilAttachment has already been put onto // the GrRenderTarget. This function must return false if any failures occur when completing the // stencil attachment. virtual bool completeStencilAttachment() = 0; friend class GrRenderTargetPriv; GrStencilAttachment* fStencilAttachment; SampleConfig fSampleConfig; SkIRect fResolveRect; // The last drawTarget that wrote to or is currently going to write to this renderTarget // The drawTarget can be closed (e.g., no draw context is currently bound // to this renderTarget). // This back-pointer is required so that we can add a dependancy between // the drawTarget used to create the current contents of this renderTarget // and the drawTarget of a destination renderTarget to which this one is being drawn. GrDrawTarget* fLastDrawTarget; typedef GrSurface INHERITED; }; #endif