Add replacement APIs for createPlatformSurface: createPlatformTexture and createPlatformRenderTarget
git-svn-id: http://skia.googlecode.com/svn/trunk@2611 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index c58d5b1..b809c99 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -464,15 +464,13 @@
reinterpret_cast<GrPlatform3DContext>(glctx.get()->gl());
context = GrContext::Create(kOpenGL_Shaders_GrEngine, ctx);
if (NULL != context) {
- GrPlatformSurfaceDesc desc;
- desc.reset();
+ GrPlatformRenderTargetDesc desc;
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fWidth = contextWidth;
desc.fHeight = contextHeight;
desc.fStencilBits = 8;
- desc.fPlatformRenderTarget = glctx.get()->getFBOID();
- desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
- rt = static_cast<GrRenderTarget*>(context->createPlatformSurface(desc));
+ desc.fRenderTargetHandle = glctx.get()->getFBOID();
+ rt = context->createPlatformRenderTarget(desc);
if (NULL == rt) {
context->unref();
context = NULL;
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index f2ab703..f437906 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -647,15 +647,13 @@
reinterpret_cast<GrPlatform3DContext>(glContext.get()->gl());
gGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, ctx);
if (NULL != gGrContext) {
- GrPlatformSurfaceDesc desc;
- desc.reset();
+ GrPlatformRenderTargetDesc desc;
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fWidth = maxW;
desc.fHeight = maxH;
desc.fStencilBits = 8;
- desc.fPlatformRenderTarget = glContext.get()->getFBOID();
- desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
- rt = static_cast<GrRenderTarget*>(gGrContext->createPlatformSurface(desc));
+ desc.fRenderTargetHandle = glContext.get()->getFBOID();
+ rt = gGrContext->createPlatformRenderTarget(desc);
if (NULL == rt) {
gGrContext->unref();
gGrContext = NULL;
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index d61b8bb..5e132a2 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -238,6 +238,35 @@
// Platform Surfaces
/**
+ * Wraps an existing texture with a GrTexture object.
+ *
+ * OpenGL: if the object is a texture Gr may change its GL texture params
+ * when it is drawn.
+ *
+ * @param desc description of the object to create.
+ *
+ * @return GrTexture object or NULL on failure.
+ */
+ GrTexture* createPlatformTexture(const GrPlatformTextureDesc& desc);
+
+ /**
+ * Wraps an existing render target with a GrRenderTarget object. It is
+ * similar to createPlatformTexture but can be used to draw into surfaces
+ * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
+ * the client will resolve to a texture).
+ *
+ * @param desc description of the object to create.
+ *
+ * @return GrTexture object or NULL on failure.
+ */
+ GrRenderTarget* createPlatformRenderTarget(
+ const GrPlatformRenderTargetDesc& desc);
+
+ /**
+ * This interface is depracted and will be removed in a future revision.
+ * Callers should use createPlatformTexture or createPlatformRenderTarget
+ * instead.
+ *
* 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
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index 5e9cdb2..bb19c35 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -504,6 +504,99 @@
///////////////////////////////////////////////////////////////////////////////
+// opaque type for 3D API object handles
+typedef intptr_t GrPlatform3DObject;
+
+/**
+ * Gr can wrap an existing texture created by the client with a GrTexture
+ * object. The client is responsible for ensuring that the texture lives at
+ * least as long as the GrTexture object wrapping it. We require the client to
+ * explicitly provide information about the texture, such as width, height,
+ * and pixel config, rather than querying the 3D APIfor these values. We expect
+ * these to be immutable even if the 3D API doesn't require this (OpenGL).
+ *
+ * Textures that are also render targets are supported as well. Gr will manage
+ * any ancillary 3D API (stencil buffer, FBO id, etc) objects necessary for
+ * Gr to draw into the render target. To access the render target object
+ * call GrTexture::asRenderTarget().
+ *
+ * If in addition to the render target flag, the caller also specifies a sample
+ * count Gr will create an MSAA buffer that resolves into the texture. Gr auto-
+ * resolves when it reads from the texture. The client can explictly resolve
+ * using the GrRenderTarget interface.
+ */
+
+enum GrPlatformTextureFlags {
+ /**
+ * No flags enabled
+ */
+ kNone_GrPlatformTextureFlag = 0x0,
+ /**
+ * Indicates that the texture is also a render target, and thus should have
+ * a GrRenderTarget object.
+ *
+ * D3D (future): client must have created the texture with flags that allow
+ * it to be used as a render target.
+ */
+ kRenderTarget_GrPlatformTextureFlag = 0x1,
+};
+GR_MAKE_BITFIELD_OPS(GrPlatformTextureFlags)
+
+struct GrPlatformTextureDesc {
+ GrPlatformTextureDesc() { memset(this, 0, sizeof(*this)); }
+ GrPlatformTextureFlags fFlags;
+ int fWidth; //<! width in pixels
+ int fHeight; //<! height in pixels
+ GrPixelConfig fConfig; //<! color format
+ /**
+ * If the render target flag is set and sample count is greater than 0
+ * then Gr will create an MSAA buffer that resolves to the texture.
+ */
+ int fSampleCnt;
+ /**
+ * Handle to the 3D API object.
+ * OpenGL: Texture ID.
+ */
+ GrPlatform3DObject fTextureHandle;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Gr can wrap an existing render target created by the client in the 3D API
+ * with a GrRenderTarget object. The client is responsible for ensuring that the
+ * underlying 3D API object lives at least as long as the GrRenderTarget object
+ * wrapping it. We require the client to explicitly provide information about
+ * the target, such as width, height, and pixel config rather than querying the
+ * 3D API for these values. We expect these properties to be immutable even if
+ * the 3D API doesn't require this (OpenGL).
+ */
+
+struct GrPlatformRenderTargetDesc {
+ GrPlatformRenderTargetDesc() { memset(this, 0, sizeof(this)); }
+ int fWidth; //<! width in pixels
+ int fHeight; //<! height in pixels
+ GrPixelConfig fConfig; //<! color format
+ /**
+ * The number of samples per pixel. Gr uses this to influence decisions
+ * about applying other forms of antialiasing.
+ */
+ int fSampleCnt;
+ /**
+ * Number of bits of stencil per-pixel.
+ */
+ int fStencilBits;
+ /**
+ * Handle to the 3D API object.
+ * OpenGL: FBO ID
+ */
+ GrPlatform3DObject fRenderTargetHandle;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// DEPRECATED. createPlatformSurface is replaced by createPlatformTexture
+// and createPlatformRenderTarget. These enums and structs will be removed.
+
enum GrPlatformSurfaceType {
/**
* Specifies that the object being created is a render target.
@@ -537,12 +630,6 @@
GR_MAKE_BITFIELD_OPS(GrPlatformRenderTargetFlags)
-// 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
/**
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 3b32154..cedc6a5 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -182,34 +182,28 @@
if (fGrContext) {
win->attachGL();
- GrPlatformSurfaceDesc desc;
- desc.reset();
- desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
+ GrPlatformRenderTargetDesc desc;
desc.fWidth = SkScalarRound(win->width());
desc.fHeight = SkScalarRound(win->height());
desc.fConfig = kRGBA_8888_GrPixelConfig;
- GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
GR_GL_GetIntegerv(fGL, GR_GL_SAMPLES, &desc.fSampleCnt);
+ GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
GrGLint buffer;
GR_GL_GetIntegerv(fGL, GR_GL_FRAMEBUFFER_BINDING, &buffer);
- desc.fPlatformRenderTarget = buffer;
+ desc.fRenderTargetHandle = buffer;
SkSafeUnref(fGrRenderTarget);
- fGrRenderTarget = static_cast<GrRenderTarget*>(
- fGrContext->createPlatformSurface(desc));
+ fGrRenderTarget = fGrContext->createPlatformRenderTarget(desc);
}
if (NULL != fNullGrContext) {
- GrPlatformSurfaceDesc desc;
- desc.reset();
- desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
+ GrPlatformRenderTargetDesc desc;
desc.fWidth = SkScalarRound(win->width());
desc.fHeight = SkScalarRound(win->height());
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fStencilBits = 8;
desc.fSampleCnt = 0;
- desc.fPlatformRenderTarget = 0;
- fNullGrRenderTarget = static_cast<GrRenderTarget*>(
- fNullGrContext->createPlatformSurface(desc));
+ desc.fRenderTargetHandle = 0;
+ fGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
}
}
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 231cf23..f4e5e9b 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -525,6 +525,14 @@
///////////////////////////////////////////////////////////////////////////////
+GrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
+ return fGpu->createPlatformTexture(desc);
+}
+
+GrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
+ return fGpu->createPlatformRenderTarget(desc);
+}
+
GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
// validate flags here so that GrGpu subclasses don't have to check
if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
diff --git a/src/gpu/GrGLRenderTarget.h b/src/gpu/GrGLRenderTarget.h
index 5aeb36d..eb817df 100644
--- a/src/gpu/GrGLRenderTarget.h
+++ b/src/gpu/GrGLRenderTarget.h
@@ -67,7 +67,9 @@
return this->textureFBOID();
}
virtual ResolveType getResolveType() const {
- if (fRTFBOID == fTexFBOID) {
+
+ if (!this->isMultisampled() ||
+ fRTFBOID == fTexFBOID) {
// catches FBO 0 and non MSAA case
return kAutoResolves_ResolveType;
} else if (kUnresolvableFBOID == fTexFBOID) {
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index c5a8bfb..b7d1395 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -195,6 +195,25 @@
}
}
+GrTexture* GrGpu::createPlatformTexture(const GrPlatformTextureDesc& desc) {
+ this->handleDirtyContext();
+ GrTexture* tex = this->onCreatePlatformTexture(desc);
+ // TODO: defer this and attach dynamically
+ GrRenderTarget* tgt = tex->asRenderTarget();
+ if (NULL != tgt &&
+ !this->attachStencilBufferToRenderTarget(tgt)) {
+ tex->unref();
+ return NULL;
+ } else {
+ return tex;
+ }
+}
+
+GrRenderTarget* GrGpu::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
+ this->handleDirtyContext();
+ return this->onCreatePlatformRenderTarget(desc);
+}
+
GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
this->handleDirtyContext();
return this->onCreatePlatformSurface(desc);
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 5d9cf4f..b0aaa18 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -121,6 +121,19 @@
GrTexture* createTexture(const GrTextureDesc& desc,
const void* srcData, size_t rowBytes);
+ /**
+ * Implements GrContext::createPlatformTexture
+ */
+ GrTexture* createPlatformTexture(const GrPlatformTextureDesc& desc);
+
+ /**
+ * Implements GrContext::createPlatformTexture
+ */
+ GrRenderTarget* createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc);
+
+ /**
+ * DEPRECATED. This will be removed.
+ */
GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
/**
@@ -314,6 +327,8 @@
virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) = 0;
+ virtual GrTexture* onCreatePlatformTexture(const GrPlatformTextureDesc& desc) = 0;
+ virtual GrRenderTarget* onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) = 0;
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) = 0;
virtual GrVertexBuffer* onCreateVertexBuffer(uint32_t size,
bool dynamic) = 0;
diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp
index 10c0fa6..bae4f77 100644
--- a/src/gpu/GrGpuGL.cpp
+++ b/src/gpu/GrGpuGL.cpp
@@ -634,6 +634,81 @@
fHWDrawState.fRenderTarget = NULL;
}
+GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) {
+ GrGLenum internalFormat; // we don't need this value
+ GrGLTexture::Desc glTexDesc;
+ if (!this->canBeTexture(desc.fConfig, &internalFormat,
+ &glTexDesc.fUploadFormat, &glTexDesc.fUploadType)) {
+ return NULL;
+ }
+
+ glTexDesc.fContentWidth = glTexDesc.fAllocWidth = desc.fWidth;
+ glTexDesc.fContentHeight = glTexDesc.fAllocHeight = desc.fHeight;
+ glTexDesc.fConfig = desc.fConfig;
+ glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
+ glTexDesc.fOwnsID = false;
+ glTexDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
+
+ GrGLTexture* texture = NULL;
+ if (desc.fFlags & kRenderTarget_GrPlatformTextureFlag) {
+ GrGLRenderTarget::Desc glRTDesc;
+ glRTDesc.fRTFBOID = 0;
+ glRTDesc.fTexFBOID = 0;
+ glRTDesc.fMSColorRenderbufferID = 0;
+ glRTDesc.fOwnIDs = true;
+ glRTDesc.fConfig = desc.fConfig;
+ glRTDesc.fSampleCnt = desc.fSampleCnt;
+ if (!this->createRenderTargetObjects(glTexDesc.fAllocWidth,
+ glTexDesc.fAllocHeight,
+ glTexDesc.fTextureID,
+ &glRTDesc)) {
+ return NULL;
+ }
+ texture = new GrGLTexture(this, glTexDesc, glRTDesc);
+ } else {
+ texture = new GrGLTexture(this, glTexDesc);
+ }
+ if (NULL == texture) {
+ return NULL;
+ }
+
+ this->setSpareTextureUnit();
+ return texture;
+}
+
+GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
+ GrGLRenderTarget::Desc glDesc;
+ glDesc.fConfig = desc.fConfig;
+ glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle);
+ glDesc.fMSColorRenderbufferID = 0;
+ glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
+ glDesc.fSampleCnt = desc.fSampleCnt;
+ glDesc.fOwnIDs = false;
+ GrGLIRect viewport;
+ viewport.fLeft = 0;
+ viewport.fBottom = 0;
+ viewport.fWidth = desc.fWidth;
+ viewport.fHeight = desc.fHeight;
+
+ GrRenderTarget* tgt = new GrGLRenderTarget(this, glDesc, viewport);
+ if (desc.fStencilBits) {
+ GrGLStencilBuffer::Format format;
+ format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
+ format.fPacked = false;
+ format.fStencilBits = desc.fStencilBits;
+ format.fTotalBits = desc.fStencilBits;
+ GrGLStencilBuffer* sb = new GrGLStencilBuffer(this,
+ 0,
+ desc.fWidth,
+ desc.fHeight,
+ desc.fSampleCnt,
+ format);
+ tgt->setStencilBuffer(sb);
+ sb->unref();
+ }
+ return tgt;
+}
+
GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
@@ -868,7 +943,10 @@
// If we are using multisampling we will create two FBOS. We render
// to one and then resolve to the texture bound to the other.
- if (desc->fSampleCnt > 1 && GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType) {
+ if (desc->fSampleCnt > 0) {
+ if (GLCaps::kNone_MSFBO == fGLCaps.fMSFBOType) {
+ goto FAILED;
+ }
GL_CALL(GenFramebuffers(1, &desc->fRTFBOID));
GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
if (!desc->fRTFBOID ||
@@ -949,12 +1027,6 @@
++fStats.fTextureCreateCnt;
#endif
- static const GrGLTexture::TexParams DEFAULT_PARAMS = {
- GR_GL_NEAREST,
- GR_GL_CLAMP_TO_EDGE,
- GR_GL_CLAMP_TO_EDGE
- };
-
GrGLTexture::Desc glTexDesc;
GrGLRenderTarget::Desc glRTDesc;
GrGLenum internalFormat;
@@ -1025,24 +1097,32 @@
this->setSpareTextureUnit();
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
+
+ // Some drivers like to know these before seeing glTexImage2D. Some drivers
+ // have a bug where an FBO won't be complete if it includes a texture that
+ // is not complete (i.e. has mip levels or non-mip min filter).
+ static const GrGLTexture::TexParams DEFAULT_TEX_PARAMS = {
+ GR_GL_NEAREST,
+ GR_GL_CLAMP_TO_EDGE,
+ GR_GL_CLAMP_TO_EDGE
+ };
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_MAG_FILTER,
- DEFAULT_PARAMS.fFilter));
+ DEFAULT_TEX_PARAMS.fFilter));
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_MIN_FILTER,
- DEFAULT_PARAMS.fFilter));
+ DEFAULT_TEX_PARAMS.fFilter));
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_WRAP_S,
- DEFAULT_PARAMS.fWrapS));
+ DEFAULT_TEX_PARAMS.fWrapS));
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_WRAP_T,
- DEFAULT_PARAMS.fWrapT));
+ DEFAULT_TEX_PARAMS.fWrapT));
this->allocateAndUploadTexData(glTexDesc, internalFormat,srcData, rowBytes);
GrGLTexture* tex;
if (renderTarget) {
- GrGLenum msColorRenderbufferFormat = -1;
#if GR_COLLECT_STATS
++fStats.fRenderTargetCreateCnt;
#endif
@@ -1057,7 +1137,7 @@
} else {
tex = new GrGLTexture(this, glTexDesc);
}
- tex->setCachedTexParams(DEFAULT_PARAMS, this->getResetTimestamp());
+ tex->setCachedTexParams(DEFAULT_TEX_PARAMS, this->getResetTimestamp());
#ifdef TRACE_TEXTURE_CREATION
GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n",
glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h
index f28f578..0addf4a 100644
--- a/src/gpu/GrGpuGL.h
+++ b/src/gpu/GrGpuGL.h
@@ -80,6 +80,8 @@
virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size,
bool dynamic);
virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc);
+ virtual GrTexture* onCreatePlatformTexture(const GrPlatformTextureDesc& desc) SK_OVERRIDE;
+ virtual GrRenderTarget* onCreatePlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) SK_OVERRIDE;
virtual bool createStencilBufferForRenderTarget(GrRenderTarget* rt,
int width, int height);
virtual bool attachStencilBufferToRenderTarget(GrStencilBuffer* sb,