From 2e7b43d33cc495663cb814a7a9d1ecdc09c31828 Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Tue, 18 Jan 2011 20:57:22 +0000 Subject: [PATCH] Remove notion of default rendertarget. This doesn't map well to usage patterns outside sample app. Make binding between SkGpuDevice and a GrRenderTarget more explicit. Create method on GrContext to wrap the current target in the 3D API with a GrRenderTarget. git-svn-id: http://skia.googlecode.com/svn/trunk@706 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gpu/include/GrContext.h | 17 ++++- gpu/include/GrGpu.h | 26 +++---- gpu/src/GrContext.cpp | 8 +-- gpu/src/GrGpu.cpp | 8 +++ gpu/src/GrGpuGL.cpp | 86 ++++++++++------------- gpu/src/GrGpuGL.h | 8 +-- gpu/src/GrGpuGLFixed.cpp | 4 +- gpu/src/GrGpuGLShaders.cpp | 4 +- gpu/src/GrGpuGLShaders2.cpp | 4 +- include/gpu/SkGpuCanvas.h | 10 ++- include/gpu/SkGpuDevice.h | 25 ++++--- include/gpu/SkGpuDeviceFactory.h | 9 ++- samplecode/SampleApp.cpp | 148 +++++++++++++++++++++++---------------- src/gpu/SkGpuCanvas.cpp | 9 ++- src/gpu/SkGpuDevice.cpp | 66 ++++++++--------- src/utils/mac/SkOSWindow_Mac.cpp | 1 + src/utils/win/SkOSWindow_Win.cpp | 3 +- 17 files changed, 245 insertions(+), 191 deletions(-) diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h index a931695..905fe50 100644 --- a/gpu/include/GrContext.h +++ b/gpu/include/GrContext.h @@ -41,7 +41,7 @@ public: * Helper to create a opengl-shader based context */ static GrContext* CreateGLShaderContext(); - + virtual ~GrContext(); /** @@ -115,6 +115,19 @@ public: int width, int height); /** + * 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 + * underlying object in its destructor and it is up to caller to guarantee + * that it remains valid while the GrRenderTarget is used. + * + * @return the newly created GrRenderTarget + */ + GrRenderTarget* createRenderTargetFrom3DApiState() { + return fGpu->createRenderTargetFrom3DApiState(); + } + + /** * Returns true if the specified use of an indexed texture is supported. */ bool supportsIndex8PixelConfig(const GrSamplerState&, int width, int height); @@ -126,8 +139,6 @@ public: const GrClip& getClip() const { return fGpu->getClip(); } void setRenderTarget(GrRenderTarget* target); - void setDefaultRenderTargetSize(uint32_t width, uint32_t height); - GrRenderTarget* defaultRenderTarget() { return fGpu->defaultRenderTarget(); } void setTexture(int stage, GrTexture* texture); void setSamplerState(int stage, const GrSamplerState&); diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h index f1fdf01..6cbe53e 100644 --- a/gpu/include/GrGpu.h +++ b/gpu/include/GrGpu.h @@ -197,6 +197,17 @@ public: int width, int height) = 0; /** + * 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 + * underlying object in its destructor and it is up to caller to guarantee + * that it remains valid while the GrRenderTarget is used. + * + * @return the newly created GrRenderTarget + */ + virtual GrRenderTarget* createRenderTargetFrom3DApiState() = 0; + + /** * Creates a vertex buffer. * * @param size size in bytes of the vertex buffer @@ -221,21 +232,6 @@ public: virtual GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic) = 0; /** - * Gets the default render target. This is the render target set in the - * 3D API at the time the GrGpu was created. - */ - virtual GrRenderTarget* defaultRenderTarget() = 0; - - /** - * At construction time the GrGpu infers the render target and viewport from - * the state of the underlying 3D API. However, a platform-specific resize - * event may occur. - * @param width new width of the default rendertarget - * @param height new height of the default rendertarget - */ - virtual void setDefaultRenderTargetSize(uint32_t width, uint32_t height) = 0; - - /** * Erase the entire render target, ignoring any clips/scissors. * * This is issued to the GPU driver immediately. diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index 94398cf..5128602 100644 --- a/gpu/src/GrContext.cpp +++ b/gpu/src/GrContext.cpp @@ -30,8 +30,8 @@ static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024; #if DEFER_TEXT_RENDERING static const uint32_t POOL_VB_SIZE = 2048 * - GrDrawTarget::VertexSize( - GrDrawTarget::kTextFormat_VertexLayoutBit | + GrDrawTarget::VertexSize( + GrDrawTarget::kTextFormat_VertexLayoutBit | GrDrawTarget::StageTexCoordVertexLayoutBit(0,0)); static const uint32_t NUM_POOL_VBS = 8; #else @@ -856,10 +856,6 @@ GrRenderTarget* GrContext::currentRenderTarget() const { return fGpu->currentRenderTarget(); } -void GrContext::setDefaultRenderTargetSize(uint32_t width, uint32_t height) { - fGpu->setDefaultRenderTargetSize(width, height); -} - void GrContext::setSamplerState(int stage, const GrSamplerState& samplerState) { fGpu->setSamplerState(stage, samplerState); } diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index fe6d0c3..c48bd19 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -178,6 +178,14 @@ void GrGpu::clipWillChange(const GrClip& clip) { bool GrGpu::setupClipAndFlushState(PrimitiveType type) { const GrIRect* r = NULL; + // we check this early because we need a valid + // render target to setup stencil clipping + // before even going into flushGraphicsState + if (NULL == fCurrDrawState.fRenderTarget) { + GrAssert(!"No render target bound."); + return false; + } + if (fCurrDrawState.fFlagBits & kClip_StateBit) { fClipState.fClipInStencil = fClip.countRects() > 1; diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp index 23636d1..084f98f 100644 --- a/gpu/src/GrGpuGL.cpp +++ b/gpu/src/GrGpuGL.cpp @@ -152,24 +152,7 @@ GrGpuGL::GrGpuGL() { resetContextHelper(); - GrGLRenderTarget::GLRenderTargetIDs defaultRTIDs; - GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&defaultRTIDs.fRTFBOID); - defaultRTIDs.fTexFBOID = defaultRTIDs.fRTFBOID; - defaultRTIDs.fMSColorRenderbufferID = 0; - defaultRTIDs.fStencilRenderbufferID = 0; - GLint vp[4]; - GR_GL_GetIntegerv(GL_VIEWPORT, vp); - fHWBounds.fViewportRect.setLTRB(vp[0], - vp[1] + vp[3], - vp[0] + vp[2], - vp[1]); - defaultRTIDs.fOwnIDs = false; - - fDefaultRenderTarget = new GrGLRenderTarget(defaultRTIDs, - fHWBounds.fViewportRect, - NULL, - this); - fHWDrawState.fRenderTarget = fDefaultRenderTarget; + fHWDrawState.fRenderTarget = NULL; fRenderTargetChanged = true; GLint maxTextureUnits; @@ -445,17 +428,13 @@ GrGpuGL::GrGpuGL() { fMinRenderTargetWidth = GrMax(fMinRenderTargetWidth, 16); fMinRenderTargetHeight = GrMax(fMinRenderTargetHeight, 16); #endif - // bind back to original FBO - GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, defaultRTIDs.fRTFBOID)); + #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; #endif - eraseStencil(0, ~0); } GrGpuGL::~GrGpuGL() { - fDefaultRenderTarget->abandon(); - fDefaultRenderTarget->unref(); } void GrGpuGL::resetContextHelper() { @@ -501,6 +480,7 @@ void GrGpuGL::resetContextHelper() { fHWBounds.fScissorRect.setLTRB(0,0,0,0); fHWBounds.fScissorEnabled = false; GR_GL(Disable(GL_SCISSOR_TEST)); + fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1); // disabling the stencil test also disables // stencil buffer writes @@ -546,6 +526,30 @@ GrRenderTarget* GrGpuGL::createPlatformRenderTarget( return rt; } +GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() { + + GrGLRenderTarget::GLRenderTargetIDs rtIDs; + + GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID); + rtIDs.fTexFBOID = rtIDs.fRTFBOID; + rtIDs.fMSColorRenderbufferID = 0; + rtIDs.fStencilRenderbufferID = 0; + + GLint vp[4]; + GR_GL_GetIntegerv(GL_VIEWPORT, vp); + GrIRect viewportRect; + viewportRect.setLTRB(vp[0], + vp[1] + vp[3], + vp[0] + vp[2], + vp[1]); + rtIDs.fOwnIDs = false; + + return new GrGLRenderTarget(rtIDs, + viewportRect, + NULL, + this); +} + // defines stencil formats from more to less preferred GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = { GR_STENCIL_INDEX8, @@ -979,10 +983,6 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc, return tex; } -GrRenderTarget* GrGpuGL::defaultRenderTarget() { - return fDefaultRenderTarget; -} - GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) { GLuint id; GR_GL(GenBuffers(1, &id)); @@ -1029,16 +1029,6 @@ GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) { return NULL; } -void GrGpuGL::setDefaultRenderTargetSize(uint32_t width, uint32_t height) { - GrIRect viewport(0, height, width, 0); - if (viewport != fDefaultRenderTarget->viewport()) { - fDefaultRenderTarget->setViewport(viewport); - if (fHWDrawState.fRenderTarget == fDefaultRenderTarget) { - fHWDrawState.fRenderTarget = NULL; - } - } -} - void GrGpuGL::flushScissor(const GrIRect* rect) { GrAssert(NULL != fCurrDrawState.fRenderTarget); const GrIRect& vp = @@ -1153,6 +1143,9 @@ bool GrGpuGL::readPixels(int left, int top, int width, int height, } void GrGpuGL::flushRenderTarget() { + + GrAssert(NULL != fCurrDrawState.fRenderTarget); + if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) { GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget; GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID())); @@ -1459,7 +1452,11 @@ void GrGpuGL::flushStencil() { } } -void GrGpuGL::flushGLStateCommon(PrimitiveType type) { +bool GrGpuGL::flushGLStateCommon(PrimitiveType type) { + + // GrGpu::setupClipAndFlushState should have already checked this + // and bailed if not true. + GrAssert(NULL != fCurrDrawState.fRenderTarget); for (int s = 0; s < kNumStages; ++s) { bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout); @@ -1521,15 +1518,7 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) { nextTexture->setTexParams(newTexParams); } else { GrAssert(!"Rendering with texture vert flag set but no texture"); - if (NULL != fHWDrawState.fTextures[s]) { - setTextureUnit(s); - GR_GL(BindTexture(GL_TEXTURE_2D, 0)); - // GrPrintf("---- bindtexture 0\n"); - #if GR_COLLECT_STATS - ++fStats.fTextureChngCnt; - #endif - fHWDrawState.fTextures[s] = NULL; - } + return false; } } } @@ -1607,6 +1596,7 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) { flushStencil(); fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits; + return true; } void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) { @@ -1645,7 +1635,7 @@ void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { // b) we set more state than just FBO based on the RT // So trash the HW state to force an RT flush next time if (fCurrDrawState.fRenderTarget == renderTarget) { - fCurrDrawState.fRenderTarget = fDefaultRenderTarget; + fCurrDrawState.fRenderTarget = NULL; } if (fHWDrawState.fRenderTarget == renderTarget) { fHWDrawState.fRenderTarget = NULL; diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h index 8c2cd80..611485d 100644 --- a/gpu/src/GrGpuGL.h +++ b/gpu/src/GrGpuGL.h @@ -42,9 +42,7 @@ public: intptr_t platformRenderTarget, int width, int height); - virtual GrRenderTarget* defaultRenderTarget(); - - virtual void setDefaultRenderTargetSize(uint32_t width, uint32_t height); + virtual GrRenderTarget* createRenderTargetFrom3DApiState(); virtual void eraseColor(GrColor color); @@ -98,7 +96,7 @@ protected: // sampler state (filtering, tiling) // FBO binding // line width - void flushGLStateCommon(PrimitiveType type); + bool flushGLStateCommon(PrimitiveType type); // set when this class changes the rendertarget. // Subclass should notice at flush time, take appropriate action, @@ -114,8 +112,6 @@ protected: GrGLExts fExts; private: - GrGLRenderTarget* fDefaultRenderTarget; - void resetContextHelper(); // notify callbacks to update state tracking when related diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp index d142b66..99a593d 100644 --- a/gpu/src/GrGpuGLFixed.cpp +++ b/gpu/src/GrGpuGLFixed.cpp @@ -140,7 +140,9 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) { } } - flushGLStateCommon(type); + if (!flushGLStateCommon(type)) { + return false; + } if (fRenderTargetChanged) { flushProjectionMatrix(); diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp index 7cd1891..03d4674 100644 --- a/gpu/src/GrGpuGLShaders.cpp +++ b/gpu/src/GrGpuGLShaders.cpp @@ -741,7 +741,9 @@ bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) { } } - flushGLStateCommon(type); + if (!flushGLStateCommon(type)) { + return false; + } if (fRenderTargetChanged) { // our coords are in pixel space and the GL matrices map to NDC diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp index e47fe5d..1218a36 100644 --- a/gpu/src/GrGpuGLShaders2.cpp +++ b/gpu/src/GrGpuGLShaders2.cpp @@ -1233,7 +1233,9 @@ void GrGpuGLShaders2::flushProgram(PrimitiveType type) { bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) { - flushGLStateCommon(type); + if (!flushGLStateCommon(type)) { + return false; + } if (fRenderTargetChanged) { // our coords are in pixel space and the GL matrices map to NDC diff --git a/include/gpu/SkGpuCanvas.h b/include/gpu/SkGpuCanvas.h index 8194e12..57a4b1b 100644 --- a/include/gpu/SkGpuCanvas.h +++ b/include/gpu/SkGpuCanvas.h @@ -21,6 +21,7 @@ #include "SkCanvas.h" class GrContext; +class GrRenderTarget; /** * Subclass of canvas that creates devices compatible with the GrContext pass @@ -32,8 +33,15 @@ public: * The GrContext object is reference counted. When passed to our * constructor, its reference count is incremented. In our destructor, the * GrGpu's reference count will be decremented. + * GrRenderTarget represents the rendering destination in the underlying + * 3D API. Its reference count is incremented in the constructor and + * decremented in the destructor. + * SkGpuDevice::Current3DApiRenderTarget() can be passed as a special + * value that will cause the factory to create a render target object + * that reflects the state of the underlying 3D API at the time of + * construction. */ - explicit SkGpuCanvas(GrContext*); + explicit SkGpuCanvas(GrContext*, GrRenderTarget*); virtual ~SkGpuCanvas(); /** diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index 141ed96..9c612c5 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -32,7 +32,22 @@ class GrTextContext; */ class SkGpuDevice : public SkDevice { public: - SkGpuDevice(GrContext*, const SkBitmap& bitmap, bool isLayer); + /** + * The SkGpuDevice will render to the GrRenderTarget, or if the paremeter is + * null it will create its own render target and manage that target's + * lifetime. + */ + SkGpuDevice(GrContext*, + const SkBitmap& bitmap, + GrRenderTarget* renderTargetOrNull); + + /** + * Magic value that can be passed to constructor. Causes + * the device to infer rendertarget from underlying 3D API (e.g. GL or D3D). + * This isn't a valid pointer, don't attempt to dereference. + */ + static GrRenderTarget* Current3DApiRenderTarget(); + virtual ~SkGpuDevice(); GrContext* context() const { return fContext; } @@ -46,14 +61,6 @@ public: */ intptr_t getLayerTextureHandle() const; - /** - * Attaches the device to a rendering surface. This device will then render - * to the surface. - * For example, in OpenGL, the device will interpret handle as an FBO ID - * and drawing to the device would direct GL to the FBO. - */ - void bindDeviceToTargetHandle(intptr_t handle); - // call to set the clip to the specified rect void scissor(const SkIRect&); diff --git a/include/gpu/SkGpuDeviceFactory.h b/include/gpu/SkGpuDeviceFactory.h index dd57da2..5dcba6a 100644 --- a/include/gpu/SkGpuDeviceFactory.h +++ b/include/gpu/SkGpuDeviceFactory.h @@ -26,8 +26,14 @@ public: /** * The constructor will ref() the context, passing it to each device * that it creates. It will be unref()'d in the destructor + * Non-layered devices created by the factory will draw to the + * rootRenderTarget. rootRenderTarget is ref-counted by the factory. + * SkGpuDevice::Current3DApiRenderTarget() can be passed as a special + * value that will cause the factory to create a render target object + * that reflects the state of the underlying 3D API at the time of + * construction. */ - SkGpuDeviceFactory(GrContext*); + SkGpuDeviceFactory(GrContext*, GrRenderTarget* rootRenderTarget); virtual ~SkGpuDeviceFactory(); @@ -36,6 +42,7 @@ public: private: GrContext* fContext; + GrRenderTarget* fRootRenderTarget; }; #endif diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 9600b95..bf8cb6b 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -36,7 +36,7 @@ SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { gHead = NULL; gOnce = true; } - + fChain = gHead; gHead = this; } @@ -45,21 +45,6 @@ SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { #define SK_USE_SHADERS #endif -static GrContext* get_global_grctx(SkOSWindow* oswin) { - // should be pthread-local at least - static GrContext* ctx; - if (NULL == ctx) { -#if defined(SK_SUPPORT_GL) - #if defined(SK_USE_SHADERS) - ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL); - #else - ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL); - #endif -#endif - } - return ctx; -} - ////////////////////////////////////////////////////////////////////////////// static const char gCharEvtName[] = "SampleCode_Char_Event"; @@ -156,12 +141,12 @@ protected: virtual bool onHandleKey(SkKey key); virtual bool onHandleChar(SkUnichar); virtual void onSizeChange(); - + virtual SkCanvas* beforeChildren(SkCanvas*); virtual void afterChildren(SkCanvas*); virtual void beforeChild(SkView* child, SkCanvas* canvas); virtual void afterChild(SkView* child, SkCanvas* canvas); - + virtual bool onEvent(const SkEvent& evt); virtual bool onQuery(SkEvent* evt); @@ -170,18 +155,21 @@ protected: virtual bool handleEvent(const SkEvent& evt); virtual bool handleKey(SkKey key); virtual bool handleKeyUp(SkKey key); - + virtual bool onClick(Click* click); virtual Click* onFindClickHandler(SkScalar x, SkScalar y); virtual bool onHandleKeyUp(SkKey key); #endif + private: int fCurrIndex; - + SkPicture* fPicture; SkGpuCanvas* fGpuCanvas; + GrContext* fGrContext; + GrRenderTarget* fGrRenderTarget; SkPath fClipPath; - + enum CanvasType { kRaster_CanvasType, kPicture_CanvasType, @@ -196,9 +184,11 @@ private: bool fRotate; bool fScale; bool fRequestGrabImage; - + int fScrollTestX, fScrollTestY; - + + bool make3DReady(); + void loadView(SkView*); void updateTitle(); bool nextSample(); @@ -209,13 +199,48 @@ private: evt->post(this->getSinkID(), ANIMATING_DELAY); } } - - + + static CanvasType cycle_canvastype(CanvasType); typedef SkOSWindow INHERITED; }; +bool SampleWindow::make3DReady() { + +#if defined(SK_SUPPORT_GL) + #if defined(USE_OFFSCREEN) + // first clear the raster bitmap, so we don't see any leftover bits + bitmap.eraseColor(0); + // now setup our glcanvas + attachGL(&bitmap); + #else + attachGL(NULL); + #endif + + if (NULL == fGrContext) { + SkASSERT(NULL == fGrRenderTarget); + #if defined(SK_USE_SHADERS) + fGrContext = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL); + #else + fGrContext = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL); + #endif + if (NULL != fGrContext) { + fGrRenderTarget = fGrContext->createRenderTargetFrom3DApiState(); + } + } + + if (NULL != fGrContext) { + SkASSERT(NULL != fGrRenderTarget); + return true; + } else { + detachGL(); + } +#endif + SkDebugf("Failed to setup 3D"); + return false; +} + SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) { static const CanvasType gCT[] = { kPicture_CanvasType, @@ -229,6 +254,9 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) { fPicture = NULL; fGpuCanvas = NULL; + fGrContext = NULL; + fGrRenderTarget = NULL; + #ifdef DEFAULT_TO_GPU fCanvasType = kGPU_CanvasType; #else @@ -263,6 +291,12 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) { SampleWindow::~SampleWindow() { delete fPicture; delete fGpuCanvas; + if (NULL != fGrRenderTarget) { + fGrRenderTarget->unref(); + } + if (NULL != fGrContext) { + fGrContext->unref(); + } } static SkBitmap capture_bitmap(SkCanvas* canvas) { @@ -275,7 +309,7 @@ static SkBitmap capture_bitmap(SkCanvas* canvas) { static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig, SkBitmap* diff) { const SkBitmap& src = canvas->getDevice()->accessBitmap(false); - + SkAutoLockPixels alp0(src); SkAutoLockPixels alp1(orig); for (int y = 0; y < src.height(); y++) { @@ -324,7 +358,7 @@ void SampleWindow::draw(SkCanvas* canvas) { this->INHERITED::draw(canvas); } } - + SkBitmap diff; if (bitmap_diff(canvas, orig, &diff)) { } @@ -360,13 +394,13 @@ static void reverseRedAndBlue(const SkBitmap& bm) { SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { SkIPoint viewport; bool alreadyGPU = canvas->getViewport(&viewport); - + if (kGPU_CanvasType != fCanvasType) { #ifdef SK_SUPPORT_GL detachGL(); -#endif +#endif } - + switch (fCanvasType) { case kRaster_CanvasType: canvas = this->INHERITED::beforeChildren(canvas); @@ -376,27 +410,17 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { canvas = fPicture->beginRecording(9999, 9999); break; case kGPU_CanvasType: { - if (!alreadyGPU) { + if (!alreadyGPU && make3DReady()) { SkDevice* device = canvas->getDevice(); - const SkBitmap& bitmap = device->accessBitmap(true); -#ifdef SK_SUPPORT_GL - #ifdef USE_OFFSCREEN - // first clear the raster bitmap, so we don't see any leftover bits - bitmap.eraseColor(0); - // now setup our glcanvas - attachGL(&bitmap); - #else - attachGL(NULL); - #endif - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -#endif - fGpuCanvas = new SkGpuCanvas(get_global_grctx(this)); + const SkBitmap& bitmap = device->accessBitmap(true); + + fGpuCanvas = new SkGpuCanvas(fGrContext, fGrRenderTarget); device = fGpuCanvas->createDevice(SkBitmap::kARGB_8888_Config, bitmap.width(), bitmap.height(), false, false); fGpuCanvas->setDevice(device)->unref(); canvas = fGpuCanvas; - + } else { canvas = this->INHERITED::beforeChildren(canvas); } @@ -425,7 +449,7 @@ static void paint_rgn(const SkBitmap& bm, const SkIRect& r, void SampleWindow::afterChildren(SkCanvas* orig) { if (fRequestGrabImage) { fRequestGrabImage = false; - + SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig; SkDevice* device = canvas->getDevice(); SkBitmap bitmap; @@ -452,7 +476,7 @@ void SampleWindow::afterChildren(SkCanvas* orig) { SkDynamicMemoryWStream ostream; fPicture->serialize(&ostream); fPicture->unref(); - + SkMemoryStream istream(ostream.getStream(), ostream.getOffset()); SkPicture pict(&istream); orig->drawPicture(pict); @@ -473,7 +497,7 @@ void SampleWindow::afterChildren(SkCanvas* orig) { break; #endif } - + // if ((fScrollTestX | fScrollTestY) != 0) if (false) { const SkBitmap& bm = orig->getDevice()->accessBitmap(true); @@ -481,7 +505,7 @@ void SampleWindow::afterChildren(SkCanvas* orig) { int dy = fScrollTestY * 7; SkIRect r; SkRegion inval; - + r.set(50, 50, 50+100, 50+100); bm.scrollRect(&r, dx, dy, &inval); paint_rgn(bm, r, inval); @@ -589,7 +613,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { } } } - + int dx = 0xFF; int dy = 0xFF; @@ -603,11 +627,11 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { case '9': dx = 1; dy = -1; break; case '3': dx = 1; dy = 1; break; case '1': dx = -1; dy = 1; break; - + default: break; } - + if (0xFF != dx && 0xFF != dy) { if ((dx | dy) == 0) { fScrollTestX = fScrollTestY = 0; @@ -618,7 +642,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { this->inval(NULL); return true; } - + switch (uni) { case 'a': fAnimating = !fAnimating; @@ -659,7 +683,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { default: break; } - + return this->INHERITED::onHandleChar(uni); } @@ -724,7 +748,7 @@ void SampleWindow::loadView(SkView* view) { if (prev) { prev->detachFromParent(); } - + if (NULL == view) { view = create_overview(fSamples.count(), fSamples.begin()); } @@ -768,12 +792,12 @@ void SampleWindow::updateTitle() { if (title.size() == 0) { title.set(""); } - + title.prepend(gCanvasTypePrefix[fCanvasType]); title.prepend(" "); title.prepend(configToString(this->getBitmap().config())); - + if (fAnimating) { title.prepend(" "); } @@ -795,12 +819,12 @@ void SampleWindow::onSizeChange() { SkView::F2BIter iter(this); SkView* view = iter.next(); view->setSize(this->width(), this->height()); - + // rebuild our clippath { const SkScalar W = this->width(); const SkScalar H = this->height(); - + fClipPath.reset(); #if 0 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) { @@ -817,7 +841,7 @@ void SampleWindow::onSizeChange() { fClipPath.addRect(r, SkPath::kCW_Direction); #endif } - + this->updateTitle(); // to refresh our config } @@ -838,7 +862,7 @@ template void SkTBSort(T array[], int count) { break; } } - + for (int k = 0; k < count - 1; k++) { SkASSERT(!(array[k+1] < array[k])); } @@ -909,7 +933,7 @@ static void test() { for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) { test_rects(gRecs[i].fRects, gRecs[i].fCount); } - + SkRandom rand; for (i = 0; i < 10000; i++) { SkRegion rgn0, rgn1; diff --git a/src/gpu/SkGpuCanvas.cpp b/src/gpu/SkGpuCanvas.cpp index 5ca1736..9513bbd 100644 --- a/src/gpu/SkGpuCanvas.cpp +++ b/src/gpu/SkGpuCanvas.cpp @@ -23,11 +23,14 @@ /////////////////////////////////////////////////////////////////////////////// -static SkDeviceFactory* make_df(GrContext* context) { - return SkNEW_ARGS(SkGpuDeviceFactory, (context)); +static SkDeviceFactory* make_df(GrContext* context, + GrRenderTarget* renderTarget) { + return SkNEW_ARGS(SkGpuDeviceFactory, (context, renderTarget)); } -SkGpuCanvas::SkGpuCanvas(GrContext* context) : SkCanvas(make_df(context)) { +SkGpuCanvas::SkGpuCanvas(GrContext* context, + GrRenderTarget* renderTarget) + : SkCanvas(make_df(context, renderTarget)) { SkASSERT(context); fContext = context; fContext->ref(); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index d55f6f2..f14de35 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -109,8 +109,14 @@ public: /////////////////////////////////////////////////////////////////////////////// -SkGpuDevice::SkGpuDevice(GrContext* context, const SkBitmap& bitmap, bool isLayer) - : SkDevice(NULL, bitmap, false) { +GrRenderTarget* SkGpuDevice::Current3DApiRenderTarget() { + return (GrRenderTarget*) -1; +} + +SkGpuDevice::SkGpuDevice(GrContext* context, + const SkBitmap& bitmap, + GrRenderTarget* renderTargetOrNull) + : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) { fNeedPrepareRenderTarget = false; fDrawProcs = NULL; @@ -123,7 +129,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context, const SkBitmap& bitmap, bool isLaye fRenderTarget = NULL; fNeedClear = false; - if (isLayer) { + if (NULL == renderTargetOrNull) { SkBitmap::Config c = bitmap.config(); if (c != SkBitmap::kRGB_565_Config) { c = SkBitmap::kARGB_8888_Config; @@ -164,16 +170,13 @@ SkGpuDevice::SkGpuDevice(GrContext* context, const SkBitmap& bitmap, bool isLaye } else { GrPrintf("--- failed to create gpu-offscreen [%d %d]\n", this->width(), this->height()); + GrAssert(false); } - } - - if (NULL == fRenderTarget) { - GrAssert(NULL == fCache); - GrAssert(NULL == fTexture); - - fRenderTarget = fContext->currentRenderTarget(); + } else if (Current3DApiRenderTarget() == renderTargetOrNull) { + fRenderTarget = fContext->createRenderTargetFrom3DApiState(); + } else { + fRenderTarget = renderTargetOrNull; fRenderTarget->ref(); - fContext->setDefaultRenderTargetSize(this->width(), this->height()); } } @@ -196,26 +199,6 @@ SkGpuDevice::~SkGpuDevice() { } } -void SkGpuDevice::bindDeviceToTargetHandle(intptr_t handle) { - if (fCache) { - GrAssert(NULL != fTexture); - GrAssert(fRenderTarget == fTexture->asRenderTarget()); - // IMPORTANT: reattach the rendertarget/tex back to the cache. - fContext->reattachAndUnlockCachedTexture((GrTextureEntry*)fCache); - } else if (NULL != fTexture) { - GrAssert(!CACHE_LAYER_TEXTURES); - fTexture->unref(); - } else if (NULL != fRenderTarget) { - fRenderTarget->unref(); - } - - fCache = NULL; - fTexture = NULL; - fRenderTarget = fContext->createPlatformRenderTarget(handle, - this->width(), - this->height()); -} - intptr_t SkGpuDevice::getLayerTextureHandle() const { if (fTexture) { return fTexture->getTextureHandle(); @@ -1050,12 +1033,29 @@ void SkGpuDevice::unlockCachedTexture(TexCache* cache) { /////////////////////////////////////////////////////////////////////////////// -SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context) : fContext(context) { +SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, + GrRenderTarget* rootRenderTarget) + : fContext(context) { + + GrAssert(NULL != context); + GrAssert(NULL != rootRenderTarget); + + // check this now rather than passing this value to SkGpuDevice cons. + // we want the rt that is bound *now* in the 3D API, not the one + // at the time of newDevice. + if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) { + fRootRenderTarget = context->createRenderTargetFrom3DApiState(); + } else { + fRootRenderTarget = rootRenderTarget; + rootRenderTarget->ref(); + } context->ref(); + } SkGpuDeviceFactory::~SkGpuDeviceFactory() { fContext->unref(); + fRootRenderTarget->unref(); } SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, @@ -1064,6 +1064,6 @@ SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, SkBitmap bm; bm.setConfig(config, width, height); bm.setIsOpaque(isOpaque); - return new SkGpuDevice(fContext, bm, isLayer); + return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget); } diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp index 6828a95..d4ef7e9 100644 --- a/src/utils/mac/SkOSWindow_Mac.cpp +++ b/src/utils/mac/SkOSWindow_Mac.cpp @@ -512,6 +512,7 @@ bool SkOSWindow::attachGL(const SkBitmap* offscreen) if (success) { glClearColor(0, 0, 0, 0); + glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } return success; diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp index 40455d2..53449b1 100644 --- a/src/utils/win/SkOSWindow_Win.cpp +++ b/src/utils/win/SkOSWindow_Win.cpp @@ -439,7 +439,8 @@ bool SkOSWindow::attachGL(const SkBitmap* offscreen) { } if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) { glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); fGLAttached = true; return true; } -- 2.7.4