aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-09-22 21:01:31 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-09-22 21:01:31 +0000
commit18c9c198f571997463d9a7134dbd88298e592ec2 (patch)
treeaa66d25ecdc1d33dd9c4c7e943b1ca43acd0f13f /gpu/src
parentf1fd30da32f14e6c58b10903267afb937ee64888 (diff)
Put caps in a struct, move up to GrDrawTarget
Review URL: http://codereview.appspot.com/5088049 git-svn-id: http://skia.googlecode.com/svn/trunk@2314 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/src')
-rw-r--r--gpu/src/GrAAHairLinePathRenderer.cpp2
-rw-r--r--gpu/src/GrBufferAllocPool.cpp6
-rw-r--r--gpu/src/GrContext.cpp38
-rw-r--r--gpu/src/GrDrawTarget.cpp20
-rw-r--r--gpu/src/GrDrawTarget.h37
-rw-r--r--gpu/src/GrGLIndexBuffer.cpp6
-rw-r--r--gpu/src/GrGLVertexBuffer.cpp6
-rw-r--r--gpu/src/GrGpu.cpp3
-rw-r--r--gpu/src/GrGpu.h139
-rw-r--r--gpu/src/GrGpuGL.cpp480
-rw-r--r--gpu/src/GrGpuGL.h64
-rw-r--r--gpu/src/GrGpuGLFixed.cpp3
-rw-r--r--gpu/src/GrGpuGLShaders.cpp16
-rw-r--r--gpu/src/GrInOrderDrawBuffer.cpp12
-rw-r--r--gpu/src/GrPathRendererChain.cpp6
15 files changed, 382 insertions, 456 deletions
diff --git a/gpu/src/GrAAHairLinePathRenderer.cpp b/gpu/src/GrAAHairLinePathRenderer.cpp
index 8349fa77f1..4d05a6bb7d 100644
--- a/gpu/src/GrAAHairLinePathRenderer.cpp
+++ b/gpu/src/GrAAHairLinePathRenderer.cpp
@@ -87,7 +87,7 @@ GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
}
bool GrAAHairLinePathRenderer::CanBeUsed(const GrContext* context) {
- return context->getGpu()->supportsShaderDerivatives();
+ return context->getGpu()->getCaps().fShaderDerivativeSupport;
}
diff --git a/gpu/src/GrBufferAllocPool.cpp b/gpu/src/GrBufferAllocPool.cpp
index 667e43789b..715d4a9bef 100644
--- a/gpu/src/GrBufferAllocPool.cpp
+++ b/gpu/src/GrBufferAllocPool.cpp
@@ -91,7 +91,7 @@ void GrBufferAllocPool::reset() {
fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
fPreallocBuffers.count();
}
- fCpuData.reset(fGpu->supportsBufferLocking() ? 0 : fMinBlockSize);
+ fCpuData.reset(fGpu->getCaps().fBufferLockSupport ? 0 : fMinBlockSize);
GrAssert(0 == fPreallocBuffersInUse);
VALIDATE();
}
@@ -276,7 +276,7 @@ bool GrBufferAllocPool::createBlock(size_t requestSize) {
GrAssert(NULL == fBufferPtr);
- if (fGpu->supportsBufferLocking() &&
+ if (fGpu->getCaps().fBufferLockSupport &&
size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
(!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
fBufferPtr = block.fBuffer->lock();
@@ -318,7 +318,7 @@ void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
GrAssert(flushSize <= buffer->sizeInBytes());
bool updated = false;
- if (fGpu->supportsBufferLocking() &&
+ if (fGpu->getCaps().fBufferLockSupport &&
flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
void* data = buffer->lock();
if (NULL != data) {
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 6de3169415..ee38d725bc 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -166,13 +166,13 @@ bool gen_texture_key_values(const GrGpu* gpu,
// we assume we only need 16 bits of width and height
// assert that texture creation will fail anyway if this assumption
// would cause key collisions.
- GrAssert(gpu->maxTextureSize() <= SK_MaxU16);
+ GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
v[0] = clientKey & 0xffffffffUL;
v[1] = (clientKey >> 32) & 0xffffffffUL;
v[2] = width | (height << 16);
v[3] = 0;
- if (!gpu->npotTextureTileSupport()) {
+ if (!gpu->getCaps().fNPOTTextureTileSupport) {
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
@@ -310,10 +310,12 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key,
rtDesc.fFlags = rtDesc.fFlags |
kRenderTarget_GrTextureFlagBit |
kNoStencil_GrTextureFlagBit;
- rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
- fGpu->minRenderTargetWidth()));
- rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
- fGpu->minRenderTargetHeight()));
+ rtDesc.fWidth =
+ GrNextPow2(GrMax<int>(desc.fWidth,
+ fGpu->getCaps().fMinRenderTargetWidth));
+ rtDesc.fHeight =
+ GrNextPow2(GrMax<int>(desc.fHeight,
+ fGpu->getCaps().fMinRenderTargetHeight));
GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
@@ -510,11 +512,11 @@ void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
}
int GrContext::getMaxTextureSize() const {
- return fGpu->maxTextureSize();
+ return fGpu->getCaps().fMaxTextureSize;
}
int GrContext::getMaxRenderTargetSize() const {
- return fGpu->maxRenderTargetSize();
+ return fGpu->getCaps().fMaxRenderTargetSize;
}
///////////////////////////////////////////////////////////////////////////////
@@ -541,21 +543,21 @@ GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc)
bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
int width, int height) const {
- if (!fGpu->supports8BitPalette()) {
+ const GrDrawTarget::Caps& caps = fGpu->getCaps();
+ if (!caps.f8BitPaletteSupport) {
return false;
}
-
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
if (!isPow2) {
- if (!fGpu->npotTextureSupport()) {
+ if (!caps.fNPOTTextureSupport) {
return false;
}
bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
- if (tiled && !fGpu->npotTextureTileSupport()) {
+ if (tiled && !caps.fNPOTTextureTileSupport) {
return false;
}
}
@@ -659,7 +661,7 @@ bool GrContext::doOffscreenAA(GrDrawTarget* target,
// Line primitves are always rasterized as 1 pixel wide.
// Super-sampling would make them too thin but MSAA would be OK.
if (isHairLines &&
- (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->supportsFullsceneAA())) {
+ (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->getCaps().fFSAASupport)) {
return false;
}
if (target->getRenderTarget()->isMultisampled()) {
@@ -708,12 +710,12 @@ bool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
desc.fFormat = kRGBA_8888_GrPixelConfig;
- if (PREFER_MSAA_OFFSCREEN_AA && fGpu->supportsFullsceneAA()) {
+ if (PREFER_MSAA_OFFSCREEN_AA && fGpu->getCaps().fFSAASupport) {
record->fDownsample = OffscreenRecord::kFSAA_Downsample;
record->fScale = 1;
desc.fAALevel = kMed_GrAALevel;
} else {
- record->fDownsample = (fGpu->supportsShaders()) ?
+ record->fDownsample = fGpu->getCaps().fShaderSupport ?
OffscreenRecord::k4x4SinglePass_Downsample :
OffscreenRecord::k4x4TwoPass_Downsample;
record->fScale = OFFSCREEN_SSAA_SCALE;
@@ -1519,7 +1521,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
////////////////////////////////////////////////////////////////////////////////
bool GrContext::supportsShaders() const {
- return fGpu->supportsShaders();
+ return fGpu->getCaps().fShaderSupport;
}
void GrContext::flush(int flagsBitfield) {
@@ -1773,8 +1775,8 @@ GrContext::GrContext(GrGpu* gpu) {
fAAFillRectIndexBuffer = NULL;
fAAStrokeRectIndexBuffer = NULL;
- int gpuMaxOffscreen = fGpu->maxRenderTargetSize();
- if (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->supportsFullsceneAA()) {
+ int gpuMaxOffscreen = gpu->getCaps().fMaxRenderTargetSize;
+ if (!PREFER_MSAA_OFFSCREEN_AA || !gpu->getCaps().fFSAASupport) {
gpuMaxOffscreen /= OFFSCREEN_SSAA_SCALE;
}
fMaxOffscreenAASize = GrMin(GR_MAX_OFFSCREEN_AA_SIZE, gpuMaxOffscreen);
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 51cff6dec3..bfcc07de80 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -1041,3 +1041,23 @@ void GrDrawTarget::AutoReleaseGeometry::reset() {
fIndices = NULL;
}
+void GrDrawTarget::Caps::print() const {
+ static const char* gNY[] = {"NO", "YES"};
+ GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
+ GrPrintf("NPOT Texture Support : %s\n", gNY[fNPOTTextureSupport]);
+ GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
+ GrPrintf("NPOT Render Target Support : %s\n", gNY[fNPOTRenderTargetSupport]);
+ GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
+ GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
+ GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
+ GrPrintf("Shader Support : %s\n", gNY[fShaderSupport]);
+ GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
+ GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
+ GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
+ GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
+ GrPrintf("Min Render Target Width : %d\n", fMinRenderTargetWidth);
+ GrPrintf("Min Render Target Height : %d\n", fMinRenderTargetHeight);
+ GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
+ GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
+}
+
diff --git a/gpu/src/GrDrawTarget.h b/gpu/src/GrDrawTarget.h
index 1d61a18fd6..a57ff81c0a 100644
--- a/gpu/src/GrDrawTarget.h
+++ b/gpu/src/GrDrawTarget.h
@@ -30,6 +30,35 @@ class GrIndexBuffer;
class GrDrawTarget : public GrRefCnt {
public:
/**
+ * Represents the draw target capabilities.
+ */
+ struct Caps {
+ Caps() { memset(this, 0, sizeof(Caps)); }
+ Caps(const Caps& c) { *this = c; }
+ Caps& operator= (const Caps& c) {
+ memcpy(this, &c, sizeof(Caps));
+ return *this;
+ }
+ void print() const;
+ bool f8BitPaletteSupport : 1;
+ bool fNPOTTextureSupport : 1;
+ bool fNPOTTextureTileSupport : 1;
+ bool fNPOTRenderTargetSupport : 1;
+ bool fTwoSidedStencilSupport : 1;
+ bool fStencilWrapOpsSupport : 1;
+ bool fHWAALineSupport : 1;
+ bool fShaderSupport : 1;
+ bool fShaderDerivativeSupport : 1;
+ bool fFSAASupport : 1;
+ bool fDualSourceBlendingSupport : 1;
+ bool fBufferLockSupport : 1;
+ int fMinRenderTargetWidth;
+ int fMinRenderTargetHeight;
+ int fMaxRenderTargetSize;
+ int fMaxTextureSize;
+ };
+
+ /**
* Number of texture stages. Each stage takes as input a color and
* 2D texture coordinates. The color input to the first enabled stage is the
* per-vertex color or the constant color (setColor/setAlpha) if there are
@@ -48,7 +77,6 @@ public:
kMaxTexCoords = kNumStages
};
-
/**
* The absolute maximum number of edges that may be specified for
* a single draw call when performing edge antialiasing. This is used for
@@ -197,6 +225,11 @@ public:
virtual ~GrDrawTarget();
/**
+ * Gets the capabilities of the draw target.
+ */
+ const Caps& getCaps() const { return fCaps; }
+
+ /**
* Sets the current clip to the region specified by clip. All draws will be
* clipped against this clip if kClip_StateBit is enabled.
*
@@ -1307,6 +1340,8 @@ protected:
DrState fCurrDrawState;
+ Caps fCaps;
+
private:
// called when setting a new vert/idx source to unref prev vb/ib
void releasePreviousVertexSource();
diff --git a/gpu/src/GrGLIndexBuffer.cpp b/gpu/src/GrGLIndexBuffer.cpp
index 27915273fe..084a4c61b0 100644
--- a/gpu/src/GrGLIndexBuffer.cpp
+++ b/gpu/src/GrGLIndexBuffer.cpp
@@ -51,7 +51,7 @@ GrGLuint GrGLIndexBuffer::bufferID() const {
void* GrGLIndexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());
- if (GPUGL->supportsBufferLocking()) {
+ if (this->getGpu()->getCaps().fBufferLockSupport) {
this->bind();
// Let driver know it can discard the old data
GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
@@ -76,7 +76,7 @@ void* GrGLIndexBuffer::lockPtr() const {
void GrGLIndexBuffer::unlock() {
GrAssert(fBufferID);
GrAssert(isLocked());
- GrAssert(GPUGL->supportsBufferLocking());
+ GrAssert(this->getGpu()->getCaps().fBufferLockSupport);
this->bind();
GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER));
@@ -85,7 +85,7 @@ void GrGLIndexBuffer::unlock() {
bool GrGLIndexBuffer::isLocked() const {
#if GR_DEBUG
- if (this->isValid() && GPUGL->supportsBufferLocking()) {
+ if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
this->bind();
GrGLint mapped;
GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER,
diff --git a/gpu/src/GrGLVertexBuffer.cpp b/gpu/src/GrGLVertexBuffer.cpp
index 2d5aee0a37..c542602a9b 100644
--- a/gpu/src/GrGLVertexBuffer.cpp
+++ b/gpu/src/GrGLVertexBuffer.cpp
@@ -50,7 +50,7 @@ GrGLuint GrGLVertexBuffer::bufferID() const {
void* GrGLVertexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());
- if (GPUGL->supportsBufferLocking()) {
+ if (this->getGpu()->getCaps().fBufferLockSupport) {
this->bind();
// Let driver know it can discard the old data
GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL,
@@ -72,7 +72,7 @@ void GrGLVertexBuffer::unlock() {
GrAssert(fBufferID);
GrAssert(isLocked());
- GrAssert(GPUGL->supportsBufferLocking());
+ GrAssert(this->getGpu()->getCaps().fBufferLockSupport);
this->bind();
GL_CALL(UnmapBuffer(GR_GL_ARRAY_BUFFER));
@@ -82,7 +82,7 @@ void GrGLVertexBuffer::unlock() {
bool GrGLVertexBuffer::isLocked() const {
GrAssert(!this->isValid() || fBufferID);
#if GR_DEBUG
- if (this->isValid() && GPUGL->supportsBufferLocking()) {
+ if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
GrGLint mapped;
this->bind();
GL_CALL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER,
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index b338d05e46..91e659d20d 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -31,8 +31,7 @@ extern void gr_run_unittests();
#define DEBUG_INVAL_START_IDX -1
GrGpu::GrGpu()
- : f8bitPaletteSupport(false)
- , fContext(NULL)
+ : fContext(NULL)
, fVertexPool(NULL)
, fIndexPool(NULL)
, fVertexPoolUseCnt(0)
diff --git a/gpu/src/GrGpu.h b/gpu/src/GrGpu.h
index e970554bcf..9ecb4b0619 100644
--- a/gpu/src/GrGpu.h
+++ b/gpu/src/GrGpu.h
@@ -54,6 +54,7 @@ struct GrGpuStats {
class GrGpu : public GrDrawTarget {
public:
+
/**
* Additional blend coeffecients for dual source blending, not exposed
* through GrPaint/GrContext.
@@ -147,118 +148,6 @@ public:
GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic);
/**
- * Are 8 bit paletted textures supported.
- *
- * @return true if 8bit palette textures are supported, false otherwise
- */
- bool supports8BitPalette() const { return f8bitPaletteSupport; }
-
- /**
- * returns true if two sided stenciling is supported. If false then only
- * the front face values of the GrStencilSettings
- * @return true if only a single stencil pass is needed.
- */
- bool supportsTwoSidedStencil() const
- { return fTwoSidedStencilSupport; }
-
- /**
- * returns true if stencil wrap is supported. If false then
- * kIncWrap_StencilOp and kDecWrap_StencilOp are treated as
- * kIncClamp_StencilOp and kDecClamp_StencilOp, respectively.
- * @return true if stencil wrap ops are supported.
- */
- bool supportsStencilWrapOps() const
- { return fStencilWrapOpsSupport; }
-
- /**
- * Checks whether locking vertex and index buffers is supported.
- *
- * @return true if locking is supported.
- */
- bool supportsBufferLocking() const { return fBufferLockSupport; }
-
- /**
- * Does the 3D API support anti-aliased lines. If so then line primitive
- * types will use this functionality when the AA state flag is set.
- */
- bool supportsHWAALines() const { return fAALineSupport; }
-
- /**
- * Are shaders supported.
- */
- bool supportsShaders() const { return fShaderSupport; }
-
- /**
- * Are derivative instructions supported in fragment shaders
- */
- bool supportsShaderDerivatives() const { return fShaderDerivativeSupport; }
-
- /**
- * Does the subclass support GrSamplerState::k4x4Downsample_Filter
- */
- bool supports4x4DownsampleFilter() const { return f4X4DownsampleFilterSupport; }
-
- /**
- * Does this instance support dual-source blending? Required for proper
- * blending with partial coverage with certain blend modes (dst coeff is
- * not 1, ISA, or ISC)
- */
- bool supportsDualSourceBlending() const {
- return fDualSourceBlendingSupport;
- }
-
- /**
- * Gets the minimum width of a render target. If a texture/rt is created
- * with a width less than this size the GrGpu object will clamp it to this
- * value.
- */
- int minRenderTargetWidth() const { return fMinRenderTargetWidth; }
-
- /**
- * Gets the minimum width of a render target. If a texture/rt is created
- * with a height less than this size the GrGpu object will clamp it to this
- * value.
- */
- int minRenderTargetHeight() const { return fMinRenderTargetHeight; }
-
- /**
- * Reports whether full scene anti-aliasing is supported.
- */
- bool supportsFullsceneAA() const { return fFSAASupport; }
-
- /**
- * Returns true if NPOT textures can be created
- *
- * @return true if NPOT textures can be created
- */
- bool npotTextureSupport() const { return fNPOTTextureSupport; }
-
- /**
- * Returns true if NPOT textures can be repeat/mirror tiled.
- *
- * @return true if NPOT textures can be tiled
- */
- bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
-
- /**
- * Returns true if a NPOT texture can be a rendertarget
- *
- * @return the true if NPOT texture/rendertarget can be created.
- */
- bool npotRenderTargetSupport() const { return fNPOTRenderTargetSupport; }
-
- /**
- * Gets the largest allowed width and height of a texture.
- */
- int maxTextureSize() const { return fMaxTextureSize; }
- /**
- * Gets the largest allowed width and height of a render target.
- */
- int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
-
- virtual void clear(const GrIRect* rect, GrColor color);
-
- /**
* Returns an index buffer that can be used to render quads.
* Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
* The max number of quads can be queried using GrIndexBuffer::maxQuads().
@@ -331,6 +220,7 @@ public:
// GrDrawTarget overrides
virtual bool willUseHWAALines() const;
+ virtual void clear(const GrIRect* rect, GrColor color);
protected:
enum PrivateStateBits {
@@ -363,31 +253,6 @@ protected:
// and the client isn't using the stencil test.
static const GrStencilSettings gClipStencilSettings;
- // defaults to false, subclass can set true to support palleted textures
- bool f8bitPaletteSupport;
-
- // set by subclass
- bool fNPOTTextureSupport;
- bool fNPOTTextureTileSupport;
- bool fNPOTRenderTargetSupport;
- bool fTwoSidedStencilSupport;
- bool fStencilWrapOpsSupport;
- bool fAALineSupport;
- bool fShaderSupport;
- bool fShaderDerivativeSupport;
- bool fFSAASupport;
- bool f4X4DownsampleFilterSupport; // supports GrSamplerState::k4x4Downsample_Filter
- bool fDualSourceBlendingSupport;
-
- // set by subclass to true if index and vertex buffers can be locked, false
- // otherwise.
- bool fBufferLockSupport;
-
- // set by subclass
- int fMinRenderTargetWidth;
- int fMinRenderTargetHeight;
- int fMaxRenderTargetSize;
- int fMaxTextureSize;
GrGpuStats fStats;
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 9906037f5d..f1d6f8a6b9 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -257,9 +257,9 @@ static int probe_for_min_render_target_width(const GrGLInterface* gl,
return minRenderTargetWidth;
}
+GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding) {
-GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
- : fStencilFormats(8) {
+ fPrintedCaps = false;
gl->ref();
fGL = gl;
@@ -303,148 +303,86 @@ GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
this->resetDirtyFlags();
+ this->initCaps();
+
+ fLastSuccessfulStencilFmtIdx = 0;
+}
+
+GrGpuGL::~GrGpuGL() {
+ // This subclass must do this before the base class destructor runs
+ // since we will unref the GrGLInterface.
+ this->releaseResources();
+ fGL->unref();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const GrGLuint kUnknownBitCount = ~0;
+
+void GrGpuGL::initCaps() {
GrGLint maxTextureUnits;
// check FS and fixed-function texture unit limits
// we only use textures in the fragment stage currently.
// checks are > to make sure we have a spare unit.
if (kES1_GrGLBinding != this->glBinding()) {
- GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
GrAssert(maxTextureUnits > kNumStages);
}
if (kES2_GrGLBinding != this->glBinding()) {
- GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
GrAssert(maxTextureUnits > kNumStages);
}
if (kES2_GrGLBinding == this->glBinding()) {
- GR_GL_GetIntegerv(gl, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
- &fMaxFragmentUniformVectors);
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
+ &fGLCaps.fMaxFragmentUniformVectors);
} else if (kDesktop_GrGLBinding != this->glBinding()) {
GrGLint max;
- GR_GL_GetIntegerv(gl, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
- fMaxFragmentUniformVectors = max / 4;
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
+ fGLCaps.fMaxFragmentUniformVectors = max / 4;
} else {
- fMaxFragmentUniformVectors = 16;
+ fGLCaps.fMaxFragmentUniformVectors = 16;
}
- ////////////////////////////////////////////////////////////////////////////
- // Check for supported features.
-
- this->setupStencilFormats();
-
GrGLint numFormats;
- GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
+ GR_GL_GetIntegerv(fGL, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
SkAutoSTMalloc<10, GrGLint> formats(numFormats);
- GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
+ GR_GL_GetIntegerv(fGL, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
for (int i = 0; i < numFormats; ++i) {
if (formats[i] == GR_GL_PALETTE8_RGBA8) {
- f8bitPaletteSupport = true;
+ fCaps.f8BitPaletteSupport = true;
break;
}
}
- if (gPrintStartupSpew) {
- GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
- }
-
- GR_STATIC_ASSERT(0 == kNone_GrAALevel);
- GR_STATIC_ASSERT(1 == kLow_GrAALevel);
- GR_STATIC_ASSERT(2 == kMed_GrAALevel);
- GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
-
- memset(fAASamples, 0, sizeof(fAASamples));
- fMSFBOType = kNone_MSFBO;
- if (kDesktop_GrGLBinding != this->glBinding()) {
- if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
- // chrome's extension is equivalent to the EXT msaa
- // and fbo_blit extensions.
- fMSFBOType = kDesktopEXT_MSFBO;
- } else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) {
- fMSFBOType = kAppleES_MSFBO;
- }
- } else {
- if ((fGLVersion >= GR_GL_VER(3,0)) || this->hasExtension("GL_ARB_framebuffer_object")) {
- fMSFBOType = kDesktopARB_MSFBO;
- } else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
- this->hasExtension("GL_EXT_framebuffer_blit")) {
- fMSFBOType = kDesktopEXT_MSFBO;
- }
- }
- if (gPrintStartupSpew) {
- switch (fMSFBOType) {
- case kNone_MSFBO:
- GrPrintf("MSAA Support: NONE\n");
- break;
- case kDesktopARB_MSFBO:
- GrPrintf("MSAA Support: DESKTOP ARB.\n");
- break;
- case kDesktopEXT_MSFBO:
- GrPrintf("MSAA Support: DESKTOP EXT.\n");
- break;
- case kAppleES_MSFBO:
- GrPrintf("MSAA Support: APPLE ES.\n");
- break;
- }
- }
-
- if (kNone_MSFBO != fMSFBOType) {
- GrGLint maxSamples;
- GR_GL_GetIntegerv(gl, GR_GL_MAX_SAMPLES, &maxSamples);
- if (maxSamples > 1 ) {
- fAASamples[kNone_GrAALevel] = 0;
- fAASamples[kLow_GrAALevel] = GrMax(2,
- GrFixedFloorToInt((GR_FixedHalf) *
- maxSamples));
- fAASamples[kMed_GrAALevel] = GrMax(2,
- GrFixedFloorToInt(((GR_Fixed1*3)/4) *
- maxSamples));
- fAASamples[kHigh_GrAALevel] = maxSamples;
- }
- if (gPrintStartupSpew) {
- GrPrintf("\tMax Samples: %d\n", maxSamples);
- }
- }
- fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
-
if (kDesktop_GrGLBinding == this->glBinding()) {
- fHasStencilWrap = (fGLVersion >= GR_GL_VER(1,4)) ||
- this->hasExtension("GL_EXT_stencil_wrap");
+ fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(1,4)) ||
+ this->hasExtension("GL_EXT_stencil_wrap");
} else {
- fHasStencilWrap = (fGLVersion >= GR_GL_VER(2,0)) ||
- this->hasExtension("GL_OES_stencil_wrap");
- }
- if (gPrintStartupSpew) {
- GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
+ fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(2,0)) ||
+ this->hasExtension("GL_OES_stencil_wrap");
}
if (kDesktop_GrGLBinding == this->glBinding()) {
// we could also look for GL_ATI_separate_stencil extension or
// GL_EXT_stencil_two_side but they use different function signatures
// than GL2.0+ (and than each other).
- fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
+ fCaps.fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
// supported on GL 1.4 and higher or by extension
- fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(1,4)) ||
- this->hasExtension("GL_EXT_stencil_wrap");
+ fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(1,4)) ||
+ this->hasExtension("GL_EXT_stencil_wrap");
} else {
// ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
// an ES1 extension.
- fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
+ fCaps.fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
// stencil wrap support is in ES2, ES1 requires extension.
- fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(2,0)) ||
- this->hasExtension("GL_OES_stencil_wrap");
- }
- if (gPrintStartupSpew) {
- GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
- (fTwoSidedStencilSupport ? "YES" : "NO"),
- (fStencilWrapOpsSupport ? "YES" : "NO"));
+ fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(2,0)) ||
+ this->hasExtension("GL_OES_stencil_wrap");
}
if (kDesktop_GrGLBinding == this->glBinding()) {
- fRGBA8Renderbuffer = true;
+ fGLCaps.fRGBA8Renderbuffer = true;
} else {
- fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
- }
- if (gPrintStartupSpew) {
- GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
+ fGLCaps.fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
}
@@ -455,101 +393,177 @@ GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
}
if (kDesktop_GrGLBinding == this->glBinding()) {
- fBufferLockSupport = true; // we require VBO support and the desktop VBO
- // extension includes glMapBuffer.
+ fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO
+ // extension includes glMapBuffer.
} else {
- fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
- }
-
- if (gPrintStartupSpew) {
- GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
+ fCaps.fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
}
if (kDesktop_GrGLBinding == this->glBinding()) {
if (fGLVersion >= GR_GL_VER(2,0) ||
this->hasExtension("GL_ARB_texture_non_power_of_two")) {
- fNPOTTextureTileSupport = true;
- fNPOTTextureSupport = true;
+ fCaps.fNPOTTextureTileSupport = true;
+ fCaps.fNPOTTextureSupport = true;
} else {
- fNPOTTextureTileSupport = false;
- fNPOTTextureSupport = false;
+ fCaps.fNPOTTextureTileSupport = false;
+ fCaps.fNPOTTextureSupport = false;
}
} else {
if (fGLVersion >= GR_GL_VER(2,0)) {
- fNPOTTextureSupport = true;
- fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
+ fCaps.fNPOTTextureSupport = true;
+ fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
} else {
- fNPOTTextureSupport =
+ fCaps.fNPOTTextureSupport =
this->hasExtension("GL_APPLE_texture_2D_limited_npot");
- fNPOTTextureTileSupport = false;
+ fCaps.fNPOTTextureTileSupport = false;
}
}
- fAALineSupport = (kDesktop_GrGLBinding == this->glBinding());
+ fCaps.fHWAALineSupport = (kDesktop_GrGLBinding == this->glBinding());
////////////////////////////////////////////////////////////////////////////
// Experiments to determine limitations that can't be queried.
// TODO: Make these a preprocess that generate some compile time constants.
// TODO: probe once at startup, rather than once per context creation.
- int expectNPOTTargets = gl->fNPOTRenderTargetSupport;
+ int expectNPOTTargets = fGL->fNPOTRenderTargetSupport;
if (expectNPOTTargets == kProbe_GrGLCapability) {
- fNPOTRenderTargetSupport =
- probe_for_npot_render_target_support(gl, fNPOTTextureSupport);
+ fCaps.fNPOTRenderTargetSupport =
+ probe_for_npot_render_target_support(fGL, fCaps.fNPOTTextureSupport);
} else {
GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
- fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
+ fCaps.fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
}
- if (gPrintStartupSpew) {
- if (fNPOTTextureSupport) {
- GrPrintf("NPOT textures supported\n");
- if (fNPOTTextureTileSupport) {
- GrPrintf("NPOT texture tiling supported\n");
- } else {
- GrPrintf("NPOT texture tiling NOT supported\n");
- }
- if (fNPOTRenderTargetSupport) {
- GrPrintf("NPOT render targets supported\n");
- } else {
- GrPrintf("NPOT render targets NOT supported\n");
- }
- } else {
- GrPrintf("NPOT textures NOT supported\n");
- }
- }
-
- GR_GL_GetIntegerv(gl, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
- GR_GL_GetIntegerv(gl, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_SIZE, &fCaps.fMaxTextureSize);
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_RENDERBUFFER_SIZE, &fCaps.fMaxRenderTargetSize);
// Our render targets are always created with textures as the color
// attachment, hence this min:
- fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
+ fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize);
- fMinRenderTargetHeight = gl->fMinRenderTargetHeight;
- if (fMinRenderTargetHeight == kProbe_GrGLCapability) {
- fMinRenderTargetHeight =
- probe_for_min_render_target_height(gl,fNPOTRenderTargetSupport,
- fMaxRenderTargetSize);
+ fCaps.fMinRenderTargetHeight = fGL->fMinRenderTargetHeight;
+ if (fCaps.fMinRenderTargetHeight == kProbe_GrGLCapability) {
+ fCaps.fMinRenderTargetHeight =
+ probe_for_min_render_target_height(fGL, fCaps.fNPOTRenderTargetSupport,
+ fCaps.fMaxRenderTargetSize);
}
- fMinRenderTargetWidth = gl->fMinRenderTargetWidth;
- if (fMinRenderTargetWidth == kProbe_GrGLCapability) {
- fMinRenderTargetWidth =
- probe_for_min_render_target_width(gl, fNPOTRenderTargetSupport,
- fMaxRenderTargetSize);
+ fCaps.fMinRenderTargetWidth = fGL->fMinRenderTargetWidth;
+ if (fCaps.fMinRenderTargetWidth == kProbe_GrGLCapability) {
+ fCaps.fMinRenderTargetWidth =
+ probe_for_min_render_target_width(fGL, fCaps.fNPOTRenderTargetSupport,
+ fCaps.fMaxRenderTargetSize);
}
- fLastSuccessfulStencilFmtIdx = 0;
+ this->initFSAASupport();
+ this->initStencilFormats();
}
-GrGpuGL::~GrGpuGL() {
- // This subclass must do this before the base class destructor runs
- // since we will unref the GrGLInterface.
- this->releaseResources();
- fGL->unref();
+void GrGpuGL::initFSAASupport() {
+ // TODO: Get rid of GrAALevel and use # samples directly.
+ GR_STATIC_ASSERT(0 == kNone_GrAALevel);
+ GR_STATIC_ASSERT(1 == kLow_GrAALevel);
+ GR_STATIC_ASSERT(2 == kMed_GrAALevel);
+ GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
+ memset(fGLCaps.fAASamples, 0, sizeof(fGLCaps.fAASamples));
+
+ fGLCaps.fMSFBOType = GLCaps::kNone_MSFBO;
+ if (kDesktop_GrGLBinding != this->glBinding()) {
+ if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
+ // chrome's extension is equivalent to the EXT msaa
+ // and fbo_blit extensions.
+ fGLCaps.fMSFBOType = GLCaps::kDesktopEXT_MSFBO;
+ } else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) {
+ fGLCaps.fMSFBOType = GLCaps::kAppleES_MSFBO;
+ }
+ } else {
+ if ((fGLVersion >= GR_GL_VER(3,0)) || this->hasExtension("GL_ARB_framebuffer_object")) {
+ fGLCaps.fMSFBOType = GLCaps::kDesktopARB_MSFBO;
+ } else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
+ this->hasExtension("GL_EXT_framebuffer_blit")) {
+ fGLCaps.fMSFBOType = GLCaps::kDesktopEXT_MSFBO;
+ }
+ }
+
+ if (GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType) {
+ GrGLint maxSamples;
+ GR_GL_GetIntegerv(fGL, GR_GL_MAX_SAMPLES, &maxSamples);
+ if (maxSamples > 1 ) {
+ fGLCaps.fAASamples[kNone_GrAALevel] = 0;
+ fGLCaps.fAASamples[kLow_GrAALevel] =
+ GrMax(2, GrFixedFloorToInt((GR_FixedHalf) * maxSamples));
+ fGLCaps.fAASamples[kMed_GrAALevel] =
+ GrMax(2, GrFixedFloorToInt(((GR_Fixed1*3)/4) * maxSamples));
+ fGLCaps.fAASamples[kHigh_GrAALevel] = maxSamples;
+ }
+ }
+ fCaps.fFSAASupport = fGLCaps.fAASamples[kHigh_GrAALevel] > 0;
+}
+
+void GrGpuGL::initStencilFormats() {
+
+ // Build up list of legal stencil formats (though perhaps not supported on
+ // the particular gpu/driver) from most preferred to least.
+
+ // these consts are in order of most preferred to least preferred
+ // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
+ static const GrGLStencilBuffer::Format
+ // internal Format stencil bits total bits packed?
+ gS8 = {GR_GL_STENCIL_INDEX8, 8, 8, false},
+ gS16 = {GR_GL_STENCIL_INDEX16, 16, 16, false},
+ gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, 32, true },
+ gS4 = {GR_GL_STENCIL_INDEX4, 4, 4, false},
+ gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false},
+ gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true };
+
+ if (kDesktop_GrGLBinding == this->glBinding()) {
+ bool supportsPackedDS = fGLVersion >= GR_GL_VER(3,0) ||
+ this->hasExtension("GL_EXT_packed_depth_stencil") ||
+ this->hasExtension("GL_ARB_framebuffer_object");
+
+ // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
+ // require FBO support we can expect these are legal formats and don't
+ // check. These also all support the unsized GL_STENCIL_INDEX.
+ fGLCaps.fStencilFormats.push_back() = gS8;
+ fGLCaps.fStencilFormats.push_back() = gS16;
+ if (supportsPackedDS) {
+ fGLCaps.fStencilFormats.push_back() = gD24S8;
+ }
+ fGLCaps.fStencilFormats.push_back() = gS4;
+ if (supportsPackedDS) {
+ fGLCaps.fStencilFormats.push_back() = gDS;
+ }
+ } else {
+ // ES2 has STENCIL_INDEX8 without extensions.
+ // ES1 with GL_OES_framebuffer_object (which we require for ES1)
+ // introduces tokens for S1 thu S8 but there are separate extensions
+ // that make them legal (GL_OES_stencil1, ...).
+ // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
+ // ES doesn't support using the unsized formats.
+
+ if (fGLVersion >= GR_GL_VER(2,0) ||
+ this->hasExtension("GL_OES_stencil8")) {
+ fGLCaps.fStencilFormats.push_back() = gS8;
+ }
+ //fStencilFormats.push_back() = gS16;
+ if (this->hasExtension("GL_OES_packed_depth_stencil")) {
+ fGLCaps.fStencilFormats.push_back() = gD24S8;
+ }
+ if (this->hasExtension("GL_OES_stencil4")) {
+ fGLCaps.fStencilFormats.push_back() = gS4;
+ }
+ // we require some stencil format.
+ GrAssert(fGLCaps.fStencilFormats.count() > 0);
+ }
}
void GrGpuGL::resetContext() {
+ if (gPrintStartupSpew && !fPrintedCaps) {
+ fPrintedCaps = true;
+ this->getCaps().print();
+ fGLCaps.print();
+ }
+
// We detect cases when blending is effectively off
fHWBlendDisabled = false;
GL_CALL(Enable(GR_GL_BLEND));
@@ -698,66 +712,6 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
}
}
-///////////////////////////////////////////////////////////////////////////////
-
-static const GrGLuint kUnknownBitCount = ~0;
-
-void GrGpuGL::setupStencilFormats() {
-
- // Build up list of legal stencil formats (though perhaps not supported on
- // the particular gpu/driver) from most preferred to least.
-
- // these consts are in order of most preferred to least preferred
- // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
- static const GrGLStencilBuffer::Format
- // internal Format stencil bits total bits packed?
- gS8 = {GR_GL_STENCIL_INDEX8, 8, 8, false},
- gS16 = {GR_GL_STENCIL_INDEX16, 16, 16, false},
- gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, 32, true },
- gS4 = {GR_GL_STENCIL_INDEX4, 4, 4, false},
- gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false},
- gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true };
-
- if (kDesktop_GrGLBinding == this->glBinding()) {
- bool supportsPackedDS = fGLVersion >= GR_GL_VER(3,0) ||
- this->hasExtension("GL_EXT_packed_depth_stencil") ||
- this->hasExtension("GL_ARB_framebuffer_object");
-
- // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
- // require FBO support we can expect these are legal formats and don't
- // check. These also all support the unsized GL_STENCIL_INDEX.
- fStencilFormats.push_back() = gS8;
- fStencilFormats.push_back() = gS16;
- if (supportsPackedDS) {
- fStencilFormats.push_back() = gD24S8;
- }
- fStencilFormats.push_back() = gS4;
- if (supportsPackedDS) {
- fStencilFormats.push_back() = gDS;
- }
- } else {
- // ES2 has STENCIL_INDEX8 without extensions.
- // ES1 with GL_OES_framebuffer_object (which we require for ES1)
- // introduces tokens for S1 thu S8 but there are separate extensions
- // that make them legal (GL_OES_stencil1, ...).
- // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
- // ES doesn't support using the unsized formats.
-
- if (fGLVersion >= GR_GL_VER(2,0) ||
- this->hasExtension("GL_OES_stencil8")) {
- fStencilFormats.push_back() = gS8;
- }
- //fStencilFormats.push_back() = gS16;
- if (this->hasExtension("GL_OES_packed_depth_stencil")) {
- fStencilFormats.push_back() = gD24S8;
- }
- if (this->hasExtension("GL_OES_stencil4")) {
- fStencilFormats.push_back() = gS4;
- }
- // we require some stencil format.
- GrAssert(fStencilFormats.count() > 0);
- }
-}
////////////////////////////////////////////////////////////////////////////////
@@ -812,7 +766,7 @@ void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc,
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, desc.fUploadByteCount));
if (kIndex_8_GrPixelConfig == desc.fFormat &&
- supports8BitPalette()) {
+ this->getCaps().f8BitPaletteSupport) {
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
GrAssert(desc.fContentWidth == desc.fAllocWidth);
GrAssert(desc.fContentHeight == desc.fAllocHeight);
@@ -920,7 +874,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
// 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 && kNone_MSFBO != fMSFBOType) {
+ if (desc->fSampleCnt > 1 && GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType) {
GL_CALL(GenFramebuffers(1, &desc->fRTFBOID));
GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
if (!desc->fRTFBOID ||
@@ -1032,39 +986,42 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
return return_null_texture();
}
+ const Caps& caps = this->getCaps();
+
// We keep GrRenderTargets in GL's normal orientation so that they
// can be drawn to by the outside world without the client having
// to render upside down.
glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
GrGLTexture::kTopDown_Orientation;
- GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
- glRTDesc.fSampleCnt = fAASamples[desc.fAALevel];
- if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
+ GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fGLCaps.fAASamples));
+ glRTDesc.fSampleCnt = fGLCaps.fAASamples[desc.fAALevel];
+ if (GLCaps::kNone_MSFBO == fGLCaps.fMSFBOType &&
+ desc.fAALevel != kNone_GrAALevel) {
GrPrintf("AA RT requested but not supported on this platform.");
}
glTexDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
if (renderTarget) {
- if (!this->npotRenderTargetSupport()) {
+ if (!caps.fNPOTRenderTargetSupport) {
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
}
- glTexDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
+ glTexDesc.fAllocWidth = GrMax(caps.fMinRenderTargetWidth,
glTexDesc.fAllocWidth);
- glTexDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
+ glTexDesc.fAllocHeight = GrMax(caps.fMinRenderTargetHeight,
glTexDesc.fAllocHeight);
- if (glTexDesc.fAllocWidth > fMaxRenderTargetSize ||
- glTexDesc.fAllocHeight > fMaxRenderTargetSize) {
+ if (glTexDesc.fAllocWidth > caps.fMaxRenderTargetSize ||
+ glTexDesc.fAllocHeight > caps.fMaxRenderTargetSize) {
return return_null_texture();
}
- } else if (!this->npotTextureSupport()) {
+ } else if (!caps.fNPOTTextureSupport) {
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
- if (glTexDesc.fAllocWidth > fMaxTextureSize ||
- glTexDesc.fAllocHeight > fMaxTextureSize) {
+ if (glTexDesc.fAllocWidth > caps.fMaxTextureSize ||
+ glTexDesc.fAllocHeight > caps.fMaxTextureSize) {
return return_null_texture();
}
}
@@ -1156,13 +1113,14 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
GrGLStencilBuffer* sb = NULL;
- int stencilFmtCnt = fStencilFormats.count();
+ int stencilFmtCnt = fGLCaps.fStencilFormats.count();
for (int i = 0; i < stencilFmtCnt; ++i) {
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
// we start with the last stencil format that succeeded in hopes
// that we won't go through this loop more than once after the
// first (painful) stencil creation.
int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
+ const GrGLStencilBuffer::Format& sFmt = fGLCaps.fStencilFormats[sIdx];
// we do this "if" so that we don't call the multisample
// version on a GL that doesn't have an MSAA extension.
if (samples > 1) {
@@ -1170,21 +1128,21 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
samples,
- fStencilFormats[sIdx].fInternalFormat,
+ sFmt.fInternalFormat,
width,
height));
} else {
GR_GL_CALL_NOERRCHECK(this->glInterface(),
RenderbufferStorage(GR_GL_RENDERBUFFER,
- fStencilFormats[sIdx].fInternalFormat,
- width, height));
+ sFmt.fInternalFormat,
+ width, height));
}
GrGLenum err = GR_GL_GET_ERROR(this->glInterface());
if (err == GR_GL_NO_ERROR) {
// After sized formats we attempt an unsized format and take whatever
// sizes GL gives us. In that case we query for the size.
- GrGLStencilBuffer::Format format = fStencilFormats[sIdx];
+ GrGLStencilBuffer::Format format = sFmt;
get_stencil_rb_sizes(this->glInterface(), sbID, &format);
sb = new GrGLStencilBuffer(this, sbID, width, height,
samples, format);
@@ -1606,7 +1564,7 @@ void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
if (rt->needsResolve()) {
- GrAssert(kNone_MSFBO != fMSFBOType);
+ GrAssert(GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType);
GrAssert(rt->textureFBOID() != rt->renderFBOID());
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
rt->renderFBOID()));
@@ -1624,7 +1582,7 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
dirtyRect.width(), dirtyRect.height());
- if (kAppleES_MSFBO == fMSFBOType) {
+ if (GLCaps::kAppleES_MSFBO == fGLCaps.fMSFBOType) {
// Apple's extension uses the scissor as the blit bounds.
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
GL_CALL(Scissor(r.fLeft, r.fBottom,
@@ -1633,10 +1591,10 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = true;
} else {
- if (kDesktopARB_MSFBO != fMSFBOType) {
+ if (GLCaps::kDesktopARB_MSFBO != fGLCaps.fMSFBOType) {
// this respects the scissor during the blit, so disable it.
- GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
- flushScissor(NULL);
+ GrAssert(GLCaps::kDesktopEXT_MSFBO == fGLCaps.fMSFBOType);
+ this->flushScissor(NULL);
}
int right = r.fLeft + r.fWidth;
int top = r.fBottom + r.fHeight;
@@ -1716,7 +1674,7 @@ void GrGpuGL::flushStencil() {
} else {
GL_CALL(Enable(GR_GL_STENCIL_TEST));
#if GR_DEBUG
- if (!fStencilWrapOpsSupport) {
+ if (!this->getCaps().fStencilWrapOpsSupport) {
GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
@@ -1768,7 +1726,7 @@ void GrGpuGL::flushStencil() {
(unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
GrAssert(settings->fBackPassOp >= 0 &&
(unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
- if (fTwoSidedStencilSupport) {
+ if (this->getCaps().fTwoSidedStencilSupport) {
GrGLenum backFunc;
unsigned int backRef = settings->fBackFuncRef;
@@ -2133,7 +2091,7 @@ bool GrGpuGL::canBeTexture(GrPixelConfig config,
*type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
break;
case kIndex_8_GrPixelConfig:
- if (this->supports8BitPalette()) {
+ if (this->getCaps().f8BitPaletteSupport) {
*format = GR_GL_PALETTE8_RGBA8;
*internalFormat = GR_GL_PALETTE8_RGBA8;
*type = GR_GL_UNSIGNED_BYTE; // unused I think
@@ -2177,7 +2135,7 @@ bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
switch (config) {
case kRGBA_8888_GrPixelConfig:
case kRGBX_8888_GrPixelConfig:
- if (fRGBA8Renderbuffer) {
+ if (fGLCaps.fRGBA8Renderbuffer) {
*format = GR_GL_RGBA8;
return true;
} else {
@@ -2267,6 +2225,32 @@ void GrGpuGL::setBuffers(bool indexed,
int GrGpuGL::getMaxEdges() const {
// FIXME: This is a pessimistic estimate based on how many other things
// want to add uniforms. This should be centralized somewhere.
- return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
+ return GR_CT_MIN(fGLCaps.fMaxFragmentUniformVectors - 8, kMaxEdges);
}
+void GrGpuGL::GLCaps::print() const {
+ for (int i = 0; i < fStencilFormats.count(); ++i) {
+ GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
+ i,
+ fStencilFormats[i].fStencilBits,
+ fStencilFormats[i].fTotalBits);
+ }
+
+ GR_STATIC_ASSERT(0 == kNone_MSFBO);
+ GR_STATIC_ASSERT(1 == kDesktopARB_MSFBO);
+ GR_STATIC_ASSERT(2 == kDesktopEXT_MSFBO);
+ GR_STATIC_ASSERT(3 == kAppleES_MSFBO);
+ static const char* gMSFBOExtStr[] = {
+ "None",
+ "ARB",
+ "EXT",
+ "Apple",
+ };
+ GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]);
+ for (int i = 0; i < GR_ARRAY_COUNT(fAASamples); ++i) {
+ GrPrintf("AA Level %d has %d samples\n", i, fAASamples[i]);
+ }
+ GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
+ GrPrintf("Support RGBA8 Render Buffer: %s\n",
+ (fRGBA8Renderbuffer ? "YES": "NO"));
+}
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index a38d6b6f70..353394fd46 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -146,9 +146,14 @@ protected:
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
private:
+ // Inits GrDrawTarget::Caps and GLCaps, sublcass may enable
+ // additional caps.
+ void initCaps();
+
+ void initFSAASupport();
// determines valid stencil formats
- void setupStencilFormats();
+ void initStencilFormats();
// notify callbacks to update state tracking when related
// objects are bound to GL or deleted outside of the class
@@ -194,7 +199,43 @@ private:
SkString fExtensionString;
GrGLVersion fGLVersion;
- SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
+ struct GLCaps {
+ // prealloc space for 8 stencil formats
+ GLCaps() : fStencilFormats(8) {}
+ SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
+
+ enum {
+ /**
+ * no support for MSAA FBOs
+ */
+ kNone_MSFBO = 0,
+ /**
+ * GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
+ */
+ kDesktopARB_MSFBO,
+ /**
+ * earlier GL_EXT_framebuffer* extensions
+ */
+ kDesktopEXT_MSFBO,
+ /**
+ * GL_APPLE_framebuffer_multisample ES extension
+ */
+ kAppleES_MSFBO,
+ } fMSFBOType;
+
+ // TODO: get rid of GrAALevel and use sample cnt directly
+ GrGLuint fAASamples[4];
+
+ // The maximum number of fragment uniform vectors (GLES has min. 16).
+ int fMaxFragmentUniformVectors;
+
+ // ES requires an extension to support RGBA8 in RenderBufferStorage
+ bool fRGBA8Renderbuffer;
+
+ void print() const;
+ } fGLCaps;
+
+
// we want to clear stencil buffers when they are created. We want to clear
// the entire buffer even if it is larger than the color attachment. We
// attach it to this fbo with no color attachment to do the initial clear.
@@ -202,23 +243,6 @@ private:
bool fHWBlendDisabled;
- GrGLuint fAASamples[4];
- enum {
- kNone_MSFBO = 0, //<! no support for MSAA FBOs
- kDesktopARB_MSFBO,//<! GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
- kDesktopEXT_MSFBO,//<! earlier GL_EXT_framebuffer* extensions
- kAppleES_MSFBO, //<! GL_APPLE_framebuffer_multisample ES extension
- } fMSFBOType;
-
- // Do we have stencil wrap ops.
- bool fHasStencilWrap;
-
- // The maximum number of fragment uniform vectors (GLES has min. 16).
- int fMaxFragmentUniformVectors;
-
- // ES requires an extension to support RGBA8 in RenderBufferStorage
- bool fRGBA8Renderbuffer;
-
int fActiveTextureUnitIdx;
// we record what stencil format worked last time to hopefully exit early
@@ -228,6 +252,8 @@ private:
const GrGLInterface* fGL;
GrGLBinding fGLBinding;
+ bool fPrintedCaps;
+
typedef GrGpu INHERITED;
};
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 2c97e69ce2..195ca32502 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -62,9 +62,6 @@ GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
GrGpuGLFixed::GrGpuGLFixed(const GrGLInterface* gl)
: GrGpuGL(gl, get_binding_in_use(gl)) {
- fShaderSupport = false;
- fShaderDerivativeSupport = false;
- fDualSourceBlendingSupport = false;
}
GrGpuGLFixed::~GrGpuGLFixed() {
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 7d15c4f134..05f6652534 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -213,7 +213,7 @@ bool GrGpuGLShaders::programUnitTest() {
bool vertexEdgeAA = random.nextF() > .5f;
if (vertexEdgeAA) {
pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit;
- if (this->supportsShaderDerivatives()) {
+ if (this->getCaps().fShaderDerivativeSupport) {
pdesc.fVertexEdgeType = random.nextF() > 0.5f ?
kHairQuad_EdgeType :
kHairLine_EdgeType;
@@ -229,7 +229,7 @@ bool GrGpuGLShaders::programUnitTest() {
pdesc.fEdgeAANumEdges = 0;
}
- if (fDualSourceBlendingSupport) {
+ if (this->getCaps().fDualSourceBlendingSupport) {
pdesc.fDualSrcOutput =
(ProgramDesc::DualSrcOutput)
(int)(random.nextF() * ProgramDesc::kDualSrcOutputCnt);
@@ -290,15 +290,15 @@ GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
: GrGpuGL(gl, get_binding_in_use(gl)) {
- fShaderSupport = true;
+ fCaps.fShaderSupport = true;
if (kDesktop_GrGLBinding == this->glBinding()) {
- fDualSourceBlendingSupport =
+ fCaps.fDualSourceBlendingSupport =
this->glVersion() >= GR_GL_VER(3,3) ||
this->hasExtension("GL_ARB_blend_func_extended");
- fShaderDerivativeSupport = true;
+ fCaps.fShaderDerivativeSupport = true;
} else {
- fDualSourceBlendingSupport = false;
- fShaderDerivativeSupport =
+ fCaps.fDualSourceBlendingSupport = false;
+ fCaps.fShaderDerivativeSupport =
this->hasExtension("GL_OES_standard_derivatives");
}
@@ -937,7 +937,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
// (e.g. solid draw, and dst coeff is kZero. It's correct to make
// the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
// kOne).
- if (fDualSourceBlendingSupport) {
+ if (this->getCaps().fDualSourceBlendingSupport) {
if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
// write the coverage value to second color
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 85af430fbf..9519655bfb 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -18,8 +18,7 @@
GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
GrVertexBufferAllocPool* vertexPool,
GrIndexBufferAllocPool* indexPool)
- : fGpu(gpu)
- , fDraws(&fDrawStorage)
+ : fDraws(&fDrawStorage)
, fStates(&fStateStorage)
, fClears(&fClearStorage)
, fClips(&fClipStorage)
@@ -33,12 +32,12 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
, fVertexPool(*vertexPool)
, fIndexPool(*indexPool)
, fGeoPoolStateStack(&fGeoStackStorage) {
-
+
+ fCaps = gpu->getCaps();
+
GrAssert(NULL != vertexPool);
GrAssert(NULL != indexPool);
- gpu->ref();
-
GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
poolState.fUsedPoolVertexBytes = 0;
poolState.fUsedPoolIndexBytes = 0;
@@ -53,7 +52,6 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
this->reset();
GrSafeUnref(fQuadIndexBuffer);
- fGpu->unref();
}
void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
@@ -627,7 +625,7 @@ void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
}
bool GrInOrderDrawBuffer::willUseHWAALines() const {
- return fGpu->supportsHWAALines() &&
+ return this->getCaps().fHWAALineSupport &&
CanUseHWAALines(this->getGeomSrc().fVertexLayout, fCurrDrawState);
}
diff --git a/gpu/src/GrPathRendererChain.cpp b/gpu/src/GrPathRendererChain.cpp
index dc09d43c1e..a6da6d3bd4 100644
--- a/gpu/src/GrPathRendererChain.cpp
+++ b/gpu/src/GrPathRendererChain.cpp
@@ -57,9 +57,9 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrDrawTarget* target,
void GrPathRendererChain::init() {
GrAssert(!fInit);
GrGpu* gpu = fOwner->getGpu();
- this->addPathRenderer(
- new GrDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
- gpu->supportsStencilWrapOps()))->unref();
+ bool twoSided = gpu->getCaps().fTwoSidedStencilSupport;
+ bool wrapOp = gpu->getCaps().fStencilWrapOpsSupport;
+ this->addPathRenderer(new GrDefaultPathRenderer(twoSided, wrapOp))->unref();
GrPathRenderer::AddPathRenderers(fOwner, fFlags, this);
fInit = true;
}