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
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 @@
* Helper to create a opengl-shader based context
*/
static GrContext* CreateGLShaderContext();
-
+
virtual ~GrContext();
/**
@@ -115,6 +115,19 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
fMinRenderTargetWidth = GrMax<GLuint>(fMinRenderTargetWidth, 16);
fMinRenderTargetHeight = GrMax<GLuint>(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 @@
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 @@
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 @@
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 @@
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 @@
}
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::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 @@
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 @@
flushStencil();
fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
+ return true;
}
void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
@@ -1645,7 +1635,7 @@
// 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 @@
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 @@
// 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 @@
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 @@
}
}
- 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 @@
}
}
- 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 @@
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 @@
* 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 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 @@
*/
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 @@
/**
* 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 @@
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 @@
gHead = NULL;
gOnce = true;
}
-
+
fChain = gHead;
gHead = this;
}
@@ -45,21 +45,6 @@
#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 @@
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 @@
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 @@
bool fRotate;
bool fScale;
bool fRequestGrabImage;
-
+
int fScrollTestX, fScrollTestY;
-
+
+ bool make3DReady();
+
void loadView(SkView*);
void updateTitle();
bool nextSample();
@@ -209,13 +199,48 @@
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 @@
fPicture = NULL;
fGpuCanvas = NULL;
+ fGrContext = NULL;
+ fGrRenderTarget = NULL;
+
#ifdef DEFAULT_TO_GPU
fCanvasType = kGPU_CanvasType;
#else
@@ -263,6 +291,12 @@
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 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 @@
this->INHERITED::draw(canvas);
}
}
-
+
SkBitmap diff;
if (bitmap_diff(canvas, orig, &diff)) {
}
@@ -360,13 +394,13 @@
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 @@
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 @@
void SampleWindow::afterChildren(SkCanvas* orig) {
if (fRequestGrabImage) {
fRequestGrabImage = false;
-
+
SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
SkDevice* device = canvas->getDevice();
SkBitmap bitmap;
@@ -452,7 +476,7 @@
SkDynamicMemoryWStream ostream;
fPicture->serialize(&ostream);
fPicture->unref();
-
+
SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
SkPicture pict(&istream);
orig->drawPicture(pict);
@@ -473,7 +497,7 @@
break;
#endif
}
-
+
// if ((fScrollTestX | fScrollTestY) != 0)
if (false) {
const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
@@ -481,7 +505,7 @@
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 @@
}
}
}
-
+
int dx = 0xFF;
int dy = 0xFF;
@@ -603,11 +627,11 @@
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 @@
this->inval(NULL);
return true;
}
-
+
switch (uni) {
case 'a':
fAnimating = !fAnimating;
@@ -659,7 +683,7 @@
default:
break;
}
-
+
return this->INHERITED::onHandleChar(uni);
}
@@ -724,7 +748,7 @@
if (prev) {
prev->detachFromParent();
}
-
+
if (NULL == view) {
view = create_overview(fSamples.count(), fSamples.begin());
}
@@ -768,12 +792,12 @@
if (title.size() == 0) {
title.set("<unknown>");
}
-
+
title.prepend(gCanvasTypePrefix[fCanvasType]);
title.prepend(" ");
title.prepend(configToString(this->getBitmap().config()));
-
+
if (fAnimating) {
title.prepend("<A> ");
}
@@ -795,12 +819,12 @@
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 @@
fClipPath.addRect(r, SkPath::kCW_Direction);
#endif
}
-
+
this->updateTitle(); // to refresh our config
}
@@ -838,7 +862,7 @@
break;
}
}
-
+
for (int k = 0; k < count - 1; k++) {
SkASSERT(!(array[k+1] < array[k]));
}
@@ -909,7 +933,7 @@
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 @@
///////////////////////////////////////////////////////////////////////////////
-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 @@
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 @@
} 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 @@
}
}
-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 @@
///////////////////////////////////////////////////////////////////////////////
-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 @@
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 @@
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 @@
}
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;
}