Reduce glGets for stencil bits.

Clean up GL vs Gr rect conventions for viewport and scissor.

Review URL: http://codereview.appspot.com/4185056/

git-svn-id: http://skia.googlecode.com/svn/trunk@813 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-02-18 16:09:55 +00:00
parent ce2b1afb58
commit 8895a7a0e2
12 changed files with 232 additions and 143 deletions

View File

@ -145,9 +145,16 @@ public:
/**
* Wraps an externally-created rendertarget in a GrRenderTarget.
* e.g. in GL platforamRenderTarget is an FBO id.
* @param platformRenderTarget 3D API-specific render target identifier
* e.g. in GL platforamRenderTarget is an FBO
* id.
* @param stencilBits the number of stencil bits that the render
* target has.
* @param width width of the render target.
* @param height height of the render target.
*/
GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
int stencilBits,
int width, int height);
/**

View File

@ -384,4 +384,40 @@ static inline void GrGLClearErr() {
#define GR_GLEXT(exts, X) exts. X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
#define GR_GLEXT_NO_ERR(exts, X) GrGLClearErr(); exts. X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
////////////////////////////////////////////////////////////////////////////////
/**
* Helpers for glGetString()
*/
bool has_gl_extension(const char* ext);
void gl_version(int* major, int* minor);
////////////////////////////////////////////////////////////////////////////////
/**
* GrGL_RestoreResetRowLength() will reset GL_UNPACK_ROW_LENGTH to 0. We write
* this wrapper, since GL_UNPACK_ROW_LENGTH is not available on all GL versions
*/
#if GR_SUPPORT_GLDESKTOP
static inline void GrGL_RestoreResetRowLength() {
GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH, 0));
}
#else
#define GrGL_RestoreResetRowLength()
#endif
////////////////////////////////////////////////////////////////////////////////
/**
* Some drivers want the var-int arg to be zero-initialized on input.
*/
#define GR_GL_INIT_ZERO 0
#define GR_GL_GetIntegerv(e, p) \
do { \
*(p) = GR_GL_INIT_ZERO; \
GR_GL(GetIntegerv(e, p)); \
} while (0)
////////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -18,15 +18,29 @@
#ifndef GrGLTexture_DEFINED
#define GrGLTexture_DEFINED
#include "GrGLConfig.h"
#include "GrGpu.h"
#include "GrTexture.h"
#include "GrRect.h"
#include "GrScalar.h"
#include "GrGLIRect.h"
class GrGpuGL;
class GrGLTexture;
class GrGLRenderTarget : public GrRenderTarget {
public:
virtual ~GrGLRenderTarget();
bool resolveable() const { return fRTFBOID != fTexFBOID; }
bool needsResolve() const { return fNeedsResolve; }
void setDirty(bool dirty) { fNeedsResolve = resolveable() && dirty; }
GLuint renderFBOID() const { return fRTFBOID; }
GLuint textureFBOID() const { return fTexFBOID; }
GLuint getStencilBits() const { return fStencilBits; }
const GrGLIRect& viewport() const { return fViewport; }
void abandon();
protected:
struct GLRenderTargetIDs {
@ -38,28 +52,15 @@ protected:
};
GrGLRenderTarget(const GLRenderTargetIDs& ids,
const GrIRect& fViewport,
GLuint stencilBits,
const GrGLIRect& fViewport,
GrGLTexture* texture,
GrGpuGL* gl);
void setViewport(const GrIRect& rect) { GrAssert(rect.height() <= 0);
fViewport = rect;}
void setViewport(const GrGLIRect& rect) { fViewport = rect; }
virtual uint32_t width() const { return fViewport.width(); }
virtual uint32_t height() const { return -fViewport.height(); }
public:
virtual ~GrGLRenderTarget();
bool resolveable() const { return fRTFBOID != fTexFBOID; }
bool needsResolve() const { return fNeedsResolve; }
void setDirty(bool dirty) { fNeedsResolve = resolveable() && dirty; }
GLuint renderFBOID() const { return fRTFBOID; }
GLuint textureFBOID() const { return fTexFBOID; }
const GrIRect& viewport() const { return fViewport; }
void abandon();
virtual int width() const { return fViewport.fWidth; }
virtual int height() const { return fViewport.fHeight; }
private:
GrGpuGL* fGL;
@ -67,6 +68,7 @@ private:
GLuint fTexFBOID;
GLuint fStencilRenderbufferID;
GLuint fMSColorRenderbufferID;
GLuint fStencilBits;
// Should this object delete IDs when it is destroyed or does someone
// else own them.
@ -79,7 +81,7 @@ private:
// when we switch to this rendertarget we want to set the viewport to
// only render to 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)
GrIRect fViewport;
GrGLIRect fViewport;
friend class GrGpuGL;
friend class GrGLTexture;
@ -111,6 +113,7 @@ protected:
GLenum fUploadFormat;
GLenum fUploadByteCount;
GLenum fUploadType;
GLuint fStencilBits;
Orientation fOrientation;
};
typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs;

View File

@ -170,11 +170,13 @@ public:
* @param platformRenderTarget handle to the the render target in the
* underlying 3D API. Interpretation depends on
* GrGpu subclass in use.
* @param stencilBits number of stencil bits the target has
* @param width width of the render target
* @param height height of the render target
*/
virtual GrRenderTarget* createPlatformRenderTarget(
intptr_t platformRenderTarget,
int stencilBits,
int width, int height) = 0;
/**
@ -351,12 +353,6 @@ protected:
// prepares clip flushes gpu state before a draw
bool setupClipAndFlushState(PrimitiveType type);
struct BoundsState {
bool fScissorEnabled;
GrIRect fScissorRect;
GrIRect fViewportRect;
};
// defaults to false, subclass can set true to support palleted textures
bool f8bitPaletteSupport;

View File

@ -34,11 +34,11 @@ public:
/**
* @return the width of the rendertarget
*/
virtual uint32_t width() const = 0;
virtual int width() const = 0;
/**
* @return the height of the rendertarget
*/
virtual uint32_t height() const = 0;
virtual int height() const = 0;
/**
* @return the texture associated with the rendertarget, may be NULL.

View File

@ -28,8 +28,6 @@
#define GR_DEBUG 1
#endif
//#define GR_FORCE_GLCHECKERR 1
/*
* The default 32bit pixel config for texture upload is GL_RGBA on all
* platforms except on Windows where it is GL_BGRA. If your bitmaps map to a

View File

@ -242,9 +242,11 @@ int GrContext::getMaxTextureDimension() {
///////////////////////////////////////////////////////////////////////////////
GrRenderTarget* GrContext::createPlatformRenderTarget(intptr_t platformRenderTarget,
GrRenderTarget* GrContext::createPlatformRenderTarget(
intptr_t platformRenderTarget,
int stencilBits,
int width, int height) {
return fGpu->createPlatformRenderTarget(platformRenderTarget,
return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,
width, height);
}

64
gpu/src/GrGLIRect.h Normal file
View File

@ -0,0 +1,64 @@
#include "GrGLConfig.h"
#ifndef GrGLIRect_DEFINED
#define GrGLIRect_DEFINED
/**
* Helper struct for dealing with the fact that Ganesh and GL use different
* window coordinate systems (top-down vs bottom-up)
*/
struct GrGLIRect {
GLint fLeft;
GLint fBottom;
GLsizei fWidth;
GLsizei fHeight;
void pushToGLViewport() const {
GR_GL(Viewport(fLeft, fBottom, fWidth, fHeight));
}
void pushToGLScissor() const {
GR_GL(Scissor(fLeft, fBottom, fWidth, fHeight));
}
void setFromGLViewport() {
GR_STATIC_ASSERT(sizeof(*this) == 4*sizeof(GLint));
GR_GL_GetIntegerv(GL_VIEWPORT, (GLint*) this);
}
// sometimes we have a GrIRect from the client that we
// want to simultaneously make relative to GL's viewport
// and convert from top-down to bottom-up.
void setRelativeTo(const GrGLIRect& glRect,
int leftOffset,
int topOffset,
int width,
int height) {
fLeft = glRect.fLeft + leftOffset;
fWidth = width;
fBottom = glRect.fBottom + (glRect.fHeight - topOffset - height);
fHeight = height;
GrAssert(fLeft >= 0);
GrAssert(fWidth >= 0);
GrAssert(fBottom >= 0);
GrAssert(fHeight >= 0);
}
bool contains(const GrGLIRect& glRect) const {
return fLeft <= glRect.fLeft &&
fBottom <= glRect.fBottom &&
fLeft + fWidth >= glRect.fLeft + glRect.fWidth &&
fBottom + fHeight >= glRect.fBottom + glRect.fHeight;
}
void invalidate() {fLeft = fWidth = fBottom = fHeight = -1;}
bool operator ==(const GrGLIRect& glRect) const {
return 0 == memcmp(this, &glRect, sizeof(GrGLIRect));
}
bool operator !=(const GrGLIRect& glRect) const {return !(*this == glRect);}
};
#endif

View File

@ -19,19 +19,19 @@
#include "GrGpuGL.h"
GrGLRenderTarget::GrGLRenderTarget(const GLRenderTargetIDs& ids,
const GrIRect& viewport,
GLuint stencilBits,
const GrGLIRect& viewport,
GrGLTexture* texture,
GrGpuGL* gl) : INHERITED(texture) {
fGL = gl;
fRTFBOID = ids.fRTFBOID;
fTexFBOID = ids.fTexFBOID;
fStencilRenderbufferID = ids.fStencilRenderbufferID;
fStencilBits = stencilBits;
fMSColorRenderbufferID = ids.fMSColorRenderbufferID;
fNeedsResolve = false;
fViewport = viewport;
fOwnIDs = ids.fOwnIDs;
// viewport should be GL's viewport with top >= bottom
GrAssert(viewport.height() <= 0);
}
GrGLRenderTarget::~GrGLRenderTarget() {
@ -99,14 +99,15 @@ GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc,
GrAssert(0 != textureDesc.fTextureID);
if (rtIDs.fTexFBOID) {
GrIRect vp;
// we render to the top left
GrGLIRect vp;
vp.fLeft = 0;
vp.fRight = (int32_t) textureDesc.fContentWidth;
// viewport for GL is top > bottom
vp.fTop = (int32_t) textureDesc.fAllocHeight;
vp.fBottom = (int32_t) textureDesc.fAllocHeight -
(int32_t)textureDesc.fContentHeight;
fRenderTarget = new GrGLRenderTarget(rtIDs, vp, this, gl);
vp.fWidth = textureDesc.fContentWidth;
vp.fHeight = textureDesc.fContentHeight;
vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
fRenderTarget = new GrGLRenderTarget(rtIDs, textureDesc.fStencilBits,
vp, this, gl);
}
}

View File

@ -458,11 +458,10 @@ void GrGpuGL::resetContextHelper() {
fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
}
GR_GL(Scissor(0,0,0,0));
fHWBounds.fScissorRect.setLTRB(0,0,0,0);
fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = false;
GR_GL(Disable(GL_SCISSOR_TEST));
fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1);
fHWBounds.fViewportRect.invalidate();
// disabling the stencil test also disables
// stencil buffer writes
@ -491,24 +490,26 @@ void GrGpuGL::resetContext() {
GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
intptr_t platformRenderTarget,
int width, int height) {
int stencilBits,
int width,
int height) {
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
rtIDs.fStencilRenderbufferID = 0;
rtIDs.fMSColorRenderbufferID = 0;
rtIDs.fTexFBOID = 0;
rtIDs.fOwnIDs = false;
GrIRect viewport;
GrGLIRect viewport;
// viewport is in GL coords (top >= bottom)
viewport.setLTRB(0, height, width, 0);
viewport.fLeft = 0;
viewport.fBottom = 0;
viewport.fWidth = width;
viewport.fHeight = height;
rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
return rt;
return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
}
GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
@ -520,37 +521,37 @@ GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
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]);
GrGLIRect viewport;
viewport.setFromGLViewport();
GLuint stencilBits;
GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&stencilBits);
rtIDs.fOwnIDs = false;
return new GrGLRenderTarget(rtIDs,
viewportRect,
NULL,
this);
return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
}
///////////////////////////////////////////////////////////////////////////////
static const GLuint UNKNOWN_BITS = ~0;
// defines stencil formats from more to less preferred
GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
GR_STENCIL_INDEX8,
struct {
GLenum fEnum;
GLuint fBits;
} gStencilFormats[] = {
{GR_STENCIL_INDEX8, 8},
#if GR_SUPPORT_GLDESKTOP
GR_STENCIL_INDEX16,
{GR_STENCIL_INDEX16, 16},
#endif
GR_DEPTH24_STENCIL8,
GR_STENCIL_INDEX4,
{GR_DEPTH24_STENCIL8, 8},
{GR_STENCIL_INDEX4, 4},
#if GR_SUPPORT_GLDESKTOP
GL_STENCIL_INDEX,
GR_DEPTH_STENCIL,
{GL_STENCIL_INDEX, UNKNOWN_BITS},
{GR_DEPTH_STENCIL, UNKNOWN_BITS}
#endif
};
@ -588,6 +589,7 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
glDesc.fContentHeight = desc.fHeight;
glDesc.fAllocWidth = desc.fWidth;
glDesc.fAllocHeight = desc.fHeight;
glDesc.fStencilBits = 0;
glDesc.fFormat = desc.fFormat;
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
@ -800,7 +802,7 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
GrAssert(0 != rtIDs.fStencilRenderbufferID);
attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
attempts = GR_ARRAY_COUNT(gStencilFormats);
}
// someone suggested that some systems might require
@ -817,13 +819,13 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
GR_RENDERBUFFER,
samples,
GR_GL_STENCIL_FORMAT_ARRAY[i],
gStencilFormats[i].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
} else {
GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
GR_RENDERBUFFER,
GR_GL_STENCIL_FORMAT_ARRAY[i],
gStencilFormats[i].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
}
@ -927,6 +929,13 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
}
// we're successful!
failed = false;
if (rtIDs.fStencilRenderbufferID) {
if (UNKNOWN_BITS == gStencilFormats[i].fBits) {
GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&glDesc.fStencilBits);
} else {
glDesc.fStencilBits = gStencilFormats[i].fBits;
}
}
break;
}
if (failed) {
@ -1020,29 +1029,23 @@ GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
void GrGpuGL::flushScissor(const GrIRect* rect) {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
const GrIRect& vp =
const GrGLIRect& vp =
((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
if (NULL != rect &&
rect->contains(vp)) {
GrGLIRect scissor;
if (NULL != rect) {
scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
rect->width(), rect->height());
if (scissor.contains(vp)) {
rect = NULL;
}
}
if (NULL != rect) {
GrIRect scissor;
// viewport is already in GL coords
// create a scissor in GL coords (top > bottom)
scissor.setLTRB(vp.fLeft + rect->fLeft,
vp.fTop - rect->fTop,
vp.fLeft + rect->fRight,
vp.fTop - rect->fBottom);
if (fHWBounds.fScissorRect != scissor) {
GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
scissor.width(), -scissor.height()));
scissor.pushToGLScissor();
fHWBounds.fScissorRect = scissor;
}
if (!fHWBounds.fScissorEnabled) {
GR_GL(Enable(GL_SCISSOR_TEST));
fHWBounds.fScissorEnabled = true;
@ -1089,8 +1092,8 @@ void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
}
void GrGpuGL::eraseStencilClip() {
GLint stencilBitCount;
GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
GrAssert(NULL != fCurrDrawState.fRenderTarget);
GLint stencilBitCount = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getStencilBits();
GrAssert(stencilBitCount > 0);
GLint clipStencilMask = (1 << (stencilBitCount - 1));
eraseStencil(0, clipStencilMask);
@ -1114,10 +1117,13 @@ bool GrGpuGL::readPixels(int left, int top, int width, int height,
}
flushRenderTarget();
const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
// Brian says that viewport rects are already upside down (grrrrr)
GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
// the read rect is viewport-relative
GrGLIRect readRect;
readRect.setRelativeTo(glvp, left, top, width, height);
GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
readRect.fWidth, readRect.fHeight,
format, type, buffer));
// now reverse the order of the rows, since GL's are bottom-to-top, but our
@ -1158,14 +1164,11 @@ void GrGpuGL::flushRenderTarget() {
GrPrintf("-- glCheckFramebufferStatus %x\n", status);
}
#endif
fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
const GrIRect& vp = rt->viewport();
fDirtyFlags.fRenderTargetChanged = true;
if (fHWBounds.fViewportRect != vp) {
GR_GL(Viewport(vp.fLeft,
vp.fBottom,
vp.width(),
-vp.height()));
fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
const GrGLIRect& vp = rt->viewport();
if (true || fHWBounds.fViewportRect != vp) {
vp.pushToGLViewport();
fHWBounds.fViewportRect = vp;
}
}
@ -1242,7 +1245,7 @@ void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
GR_GL(Enable(GL_SCISSOR_TEST));
GR_GL(Scissor(left, bottom, right-left, top-bottom));
GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
fHWBounds.fScissorRect.setEmpty();
fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = true;
} else {
GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
@ -1269,10 +1272,9 @@ void GrGpuGL::flushStencil() {
fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
if (stencilChange) {
GLint stencilBitCount;
GLint clipStencilMask;
GLint pathStencilMask;
GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
GLint stencilBitCount = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getStencilBits();
GrAssert(stencilBitCount > 0 ||
kNone_StencilPass == fCurrDrawState.fStencilPass);
clipStencilMask = (1 << (stencilBitCount - 1));

View File

@ -20,6 +20,7 @@
#include "GrGpu.h"
#include "GrGLConfig.h"
#include "GrGLIRect.h"
#include "GrGLTexture.h"
#include "GrGLVertexBuffer.h"
@ -40,6 +41,7 @@ public:
virtual GrRenderTarget* createPlatformRenderTarget(
intptr_t platformRenderTarget,
int stencilBits,
int width, int height);
virtual GrRenderTarget* createRenderTargetFrom3DApiState();
@ -87,7 +89,11 @@ protected:
void resetDirtyFlags();
// last scissor / viewport scissor state seen by the GL.
BoundsState fHWBounds;
struct {
bool fScissorEnabled;
GrGLIRect fScissorRect;
GrGLIRect fViewportRect;
} fHWBounds;
GrGLExts fExts;
@ -185,31 +191,4 @@ private:
typedef GrGpu INHERITED;
};
bool has_gl_extension(const char* ext);
void gl_version(int* major, int* minor);
/**
* GrGL_RestoreResetRowLength() will reset GL_UNPACK_ROW_LENGTH to 0. We write
* this wrapper, since GL_UNPACK_ROW_LENGTH is not available on all GL versions
*/
#if GR_SUPPORT_GLDESKTOP
static inline void GrGL_RestoreResetRowLength() {
GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH, 0));
}
#else
#define GrGL_RestoreResetRowLength()
#endif
/*
* Some drivers want the var-int arg to be zero-initialized on input.
*/
#define GR_GL_INIT_ZERO 0
#define GR_GL_GetIntegerv(e, p) \
do { \
*(p) = GR_GL_INIT_ZERO; \
GR_GL(GetIntegerv(e, p)); \
} while (0)
#endif

View File

@ -149,6 +149,7 @@
<ClInclude Include="..\..\gpu\include\GrVertexBuffer.h" />
<ClInclude Include="..\..\gpu\include\SkUIView.h" />
<ClInclude Include="..\..\gpu\src\GrBufferAllocPool.h" />
<ClInclude Include="..\..\gpu\src\GrGLIRect.h" />
<ClInclude Include="..\..\gpu\src\GrGpuGL.h" />
<ClInclude Include="..\..\gpu\src\GrGpuGLFixed.h" />
<ClInclude Include="..\..\gpu\src\GrGpuGLShaders2.h" />