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
This commit is contained in:
parent
f1fd30da32
commit
18c9c198f5
@ -87,7 +87,7 @@ GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GrAAHairLinePathRenderer::CanBeUsed(const GrContext* context) {
|
bool GrAAHairLinePathRenderer::CanBeUsed(const GrContext* context) {
|
||||||
return context->getGpu()->supportsShaderDerivatives();
|
return context->getGpu()->getCaps().fShaderDerivativeSupport;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ void GrBufferAllocPool::reset() {
|
|||||||
fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
|
fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
|
||||||
fPreallocBuffers.count();
|
fPreallocBuffers.count();
|
||||||
}
|
}
|
||||||
fCpuData.reset(fGpu->supportsBufferLocking() ? 0 : fMinBlockSize);
|
fCpuData.reset(fGpu->getCaps().fBufferLockSupport ? 0 : fMinBlockSize);
|
||||||
GrAssert(0 == fPreallocBuffersInUse);
|
GrAssert(0 == fPreallocBuffersInUse);
|
||||||
VALIDATE();
|
VALIDATE();
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ bool GrBufferAllocPool::createBlock(size_t requestSize) {
|
|||||||
|
|
||||||
GrAssert(NULL == fBufferPtr);
|
GrAssert(NULL == fBufferPtr);
|
||||||
|
|
||||||
if (fGpu->supportsBufferLocking() &&
|
if (fGpu->getCaps().fBufferLockSupport &&
|
||||||
size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
|
size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
|
||||||
(!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
|
(!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
|
||||||
fBufferPtr = block.fBuffer->lock();
|
fBufferPtr = block.fBuffer->lock();
|
||||||
@ -318,7 +318,7 @@ void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
|
|||||||
GrAssert(flushSize <= buffer->sizeInBytes());
|
GrAssert(flushSize <= buffer->sizeInBytes());
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
if (fGpu->supportsBufferLocking() &&
|
if (fGpu->getCaps().fBufferLockSupport &&
|
||||||
flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
|
flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
|
||||||
void* data = buffer->lock();
|
void* data = buffer->lock();
|
||||||
if (NULL != data) {
|
if (NULL != data) {
|
||||||
|
@ -166,13 +166,13 @@ bool gen_texture_key_values(const GrGpu* gpu,
|
|||||||
// we assume we only need 16 bits of width and height
|
// we assume we only need 16 bits of width and height
|
||||||
// assert that texture creation will fail anyway if this assumption
|
// assert that texture creation will fail anyway if this assumption
|
||||||
// would cause key collisions.
|
// would cause key collisions.
|
||||||
GrAssert(gpu->maxTextureSize() <= SK_MaxU16);
|
GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
|
||||||
v[0] = clientKey & 0xffffffffUL;
|
v[0] = clientKey & 0xffffffffUL;
|
||||||
v[1] = (clientKey >> 32) & 0xffffffffUL;
|
v[1] = (clientKey >> 32) & 0xffffffffUL;
|
||||||
v[2] = width | (height << 16);
|
v[2] = width | (height << 16);
|
||||||
|
|
||||||
v[3] = 0;
|
v[3] = 0;
|
||||||
if (!gpu->npotTextureTileSupport()) {
|
if (!gpu->getCaps().fNPOTTextureTileSupport) {
|
||||||
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
||||||
|
|
||||||
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
|
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
|
||||||
@ -310,10 +310,12 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key,
|
|||||||
rtDesc.fFlags = rtDesc.fFlags |
|
rtDesc.fFlags = rtDesc.fFlags |
|
||||||
kRenderTarget_GrTextureFlagBit |
|
kRenderTarget_GrTextureFlagBit |
|
||||||
kNoStencil_GrTextureFlagBit;
|
kNoStencil_GrTextureFlagBit;
|
||||||
rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth,
|
rtDesc.fWidth =
|
||||||
fGpu->minRenderTargetWidth()));
|
GrNextPow2(GrMax<int>(desc.fWidth,
|
||||||
rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
|
fGpu->getCaps().fMinRenderTargetWidth));
|
||||||
fGpu->minRenderTargetHeight()));
|
rtDesc.fHeight =
|
||||||
|
GrNextPow2(GrMax<int>(desc.fHeight,
|
||||||
|
fGpu->getCaps().fMinRenderTargetHeight));
|
||||||
|
|
||||||
GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
|
GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
|
||||||
|
|
||||||
@ -510,11 +512,11 @@ void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int GrContext::getMaxTextureSize() const {
|
int GrContext::getMaxTextureSize() const {
|
||||||
return fGpu->maxTextureSize();
|
return fGpu->getCaps().fMaxTextureSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GrContext::getMaxRenderTargetSize() const {
|
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,
|
bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
|
||||||
int width, int height) const {
|
int width, int height) const {
|
||||||
if (!fGpu->supports8BitPalette()) {
|
const GrDrawTarget::Caps& caps = fGpu->getCaps();
|
||||||
|
if (!caps.f8BitPaletteSupport) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
|
||||||
|
|
||||||
if (!isPow2) {
|
if (!isPow2) {
|
||||||
if (!fGpu->npotTextureSupport()) {
|
if (!caps.fNPOTTextureSupport) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
|
bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
|
||||||
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
|
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
|
||||||
if (tiled && !fGpu->npotTextureTileSupport()) {
|
if (tiled && !caps.fNPOTTextureTileSupport) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -659,7 +661,7 @@ bool GrContext::doOffscreenAA(GrDrawTarget* target,
|
|||||||
// Line primitves are always rasterized as 1 pixel wide.
|
// Line primitves are always rasterized as 1 pixel wide.
|
||||||
// Super-sampling would make them too thin but MSAA would be OK.
|
// Super-sampling would make them too thin but MSAA would be OK.
|
||||||
if (isHairLines &&
|
if (isHairLines &&
|
||||||
(!PREFER_MSAA_OFFSCREEN_AA || !fGpu->supportsFullsceneAA())) {
|
(!PREFER_MSAA_OFFSCREEN_AA || !fGpu->getCaps().fFSAASupport)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (target->getRenderTarget()->isMultisampled()) {
|
if (target->getRenderTarget()->isMultisampled()) {
|
||||||
@ -708,12 +710,12 @@ bool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
|
|||||||
|
|
||||||
desc.fFormat = kRGBA_8888_GrPixelConfig;
|
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->fDownsample = OffscreenRecord::kFSAA_Downsample;
|
||||||
record->fScale = 1;
|
record->fScale = 1;
|
||||||
desc.fAALevel = kMed_GrAALevel;
|
desc.fAALevel = kMed_GrAALevel;
|
||||||
} else {
|
} else {
|
||||||
record->fDownsample = (fGpu->supportsShaders()) ?
|
record->fDownsample = fGpu->getCaps().fShaderSupport ?
|
||||||
OffscreenRecord::k4x4SinglePass_Downsample :
|
OffscreenRecord::k4x4SinglePass_Downsample :
|
||||||
OffscreenRecord::k4x4TwoPass_Downsample;
|
OffscreenRecord::k4x4TwoPass_Downsample;
|
||||||
record->fScale = OFFSCREEN_SSAA_SCALE;
|
record->fScale = OFFSCREEN_SSAA_SCALE;
|
||||||
@ -1519,7 +1521,7 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool GrContext::supportsShaders() const {
|
bool GrContext::supportsShaders() const {
|
||||||
return fGpu->supportsShaders();
|
return fGpu->getCaps().fShaderSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrContext::flush(int flagsBitfield) {
|
void GrContext::flush(int flagsBitfield) {
|
||||||
@ -1773,8 +1775,8 @@ GrContext::GrContext(GrGpu* gpu) {
|
|||||||
fAAFillRectIndexBuffer = NULL;
|
fAAFillRectIndexBuffer = NULL;
|
||||||
fAAStrokeRectIndexBuffer = NULL;
|
fAAStrokeRectIndexBuffer = NULL;
|
||||||
|
|
||||||
int gpuMaxOffscreen = fGpu->maxRenderTargetSize();
|
int gpuMaxOffscreen = gpu->getCaps().fMaxRenderTargetSize;
|
||||||
if (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->supportsFullsceneAA()) {
|
if (!PREFER_MSAA_OFFSCREEN_AA || !gpu->getCaps().fFSAASupport) {
|
||||||
gpuMaxOffscreen /= OFFSCREEN_SSAA_SCALE;
|
gpuMaxOffscreen /= OFFSCREEN_SSAA_SCALE;
|
||||||
}
|
}
|
||||||
fMaxOffscreenAASize = GrMin(GR_MAX_OFFSCREEN_AA_SIZE, gpuMaxOffscreen);
|
fMaxOffscreenAASize = GrMin(GR_MAX_OFFSCREEN_AA_SIZE, gpuMaxOffscreen);
|
||||||
|
@ -1041,3 +1041,23 @@ void GrDrawTarget::AutoReleaseGeometry::reset() {
|
|||||||
fIndices = NULL;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,35 @@ class GrIndexBuffer;
|
|||||||
|
|
||||||
class GrDrawTarget : public GrRefCnt {
|
class GrDrawTarget : public GrRefCnt {
|
||||||
public:
|
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
|
* 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
|
* 2D texture coordinates. The color input to the first enabled stage is the
|
||||||
@ -48,7 +77,6 @@ public:
|
|||||||
kMaxTexCoords = kNumStages
|
kMaxTexCoords = kNumStages
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The absolute maximum number of edges that may be specified for
|
* The absolute maximum number of edges that may be specified for
|
||||||
* a single draw call when performing edge antialiasing. This is used for
|
* a single draw call when performing edge antialiasing. This is used for
|
||||||
@ -196,6 +224,11 @@ public:
|
|||||||
GrDrawTarget();
|
GrDrawTarget();
|
||||||
virtual ~GrDrawTarget();
|
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
|
* Sets the current clip to the region specified by clip. All draws will be
|
||||||
* clipped against this clip if kClip_StateBit is enabled.
|
* clipped against this clip if kClip_StateBit is enabled.
|
||||||
@ -1307,6 +1340,8 @@ protected:
|
|||||||
|
|
||||||
DrState fCurrDrawState;
|
DrState fCurrDrawState;
|
||||||
|
|
||||||
|
Caps fCaps;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// called when setting a new vert/idx source to unref prev vb/ib
|
// called when setting a new vert/idx source to unref prev vb/ib
|
||||||
void releasePreviousVertexSource();
|
void releasePreviousVertexSource();
|
||||||
|
@ -51,7 +51,7 @@ GrGLuint GrGLIndexBuffer::bufferID() const {
|
|||||||
void* GrGLIndexBuffer::lock() {
|
void* GrGLIndexBuffer::lock() {
|
||||||
GrAssert(fBufferID);
|
GrAssert(fBufferID);
|
||||||
GrAssert(!isLocked());
|
GrAssert(!isLocked());
|
||||||
if (GPUGL->supportsBufferLocking()) {
|
if (this->getGpu()->getCaps().fBufferLockSupport) {
|
||||||
this->bind();
|
this->bind();
|
||||||
// Let driver know it can discard the old data
|
// Let driver know it can discard the old data
|
||||||
GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
|
GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
|
||||||
@ -76,7 +76,7 @@ void* GrGLIndexBuffer::lockPtr() const {
|
|||||||
void GrGLIndexBuffer::unlock() {
|
void GrGLIndexBuffer::unlock() {
|
||||||
GrAssert(fBufferID);
|
GrAssert(fBufferID);
|
||||||
GrAssert(isLocked());
|
GrAssert(isLocked());
|
||||||
GrAssert(GPUGL->supportsBufferLocking());
|
GrAssert(this->getGpu()->getCaps().fBufferLockSupport);
|
||||||
|
|
||||||
this->bind();
|
this->bind();
|
||||||
GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER));
|
GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER));
|
||||||
@ -85,7 +85,7 @@ void GrGLIndexBuffer::unlock() {
|
|||||||
|
|
||||||
bool GrGLIndexBuffer::isLocked() const {
|
bool GrGLIndexBuffer::isLocked() const {
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
if (this->isValid() && GPUGL->supportsBufferLocking()) {
|
if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
|
||||||
this->bind();
|
this->bind();
|
||||||
GrGLint mapped;
|
GrGLint mapped;
|
||||||
GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER,
|
GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
@ -50,7 +50,7 @@ GrGLuint GrGLVertexBuffer::bufferID() const {
|
|||||||
void* GrGLVertexBuffer::lock() {
|
void* GrGLVertexBuffer::lock() {
|
||||||
GrAssert(fBufferID);
|
GrAssert(fBufferID);
|
||||||
GrAssert(!isLocked());
|
GrAssert(!isLocked());
|
||||||
if (GPUGL->supportsBufferLocking()) {
|
if (this->getGpu()->getCaps().fBufferLockSupport) {
|
||||||
this->bind();
|
this->bind();
|
||||||
// Let driver know it can discard the old data
|
// Let driver know it can discard the old data
|
||||||
GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL,
|
GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL,
|
||||||
@ -72,7 +72,7 @@ void GrGLVertexBuffer::unlock() {
|
|||||||
|
|
||||||
GrAssert(fBufferID);
|
GrAssert(fBufferID);
|
||||||
GrAssert(isLocked());
|
GrAssert(isLocked());
|
||||||
GrAssert(GPUGL->supportsBufferLocking());
|
GrAssert(this->getGpu()->getCaps().fBufferLockSupport);
|
||||||
|
|
||||||
this->bind();
|
this->bind();
|
||||||
GL_CALL(UnmapBuffer(GR_GL_ARRAY_BUFFER));
|
GL_CALL(UnmapBuffer(GR_GL_ARRAY_BUFFER));
|
||||||
@ -82,7 +82,7 @@ void GrGLVertexBuffer::unlock() {
|
|||||||
bool GrGLVertexBuffer::isLocked() const {
|
bool GrGLVertexBuffer::isLocked() const {
|
||||||
GrAssert(!this->isValid() || fBufferID);
|
GrAssert(!this->isValid() || fBufferID);
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
if (this->isValid() && GPUGL->supportsBufferLocking()) {
|
if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
|
||||||
GrGLint mapped;
|
GrGLint mapped;
|
||||||
this->bind();
|
this->bind();
|
||||||
GL_CALL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER,
|
GL_CALL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER,
|
||||||
|
@ -31,8 +31,7 @@ extern void gr_run_unittests();
|
|||||||
#define DEBUG_INVAL_START_IDX -1
|
#define DEBUG_INVAL_START_IDX -1
|
||||||
|
|
||||||
GrGpu::GrGpu()
|
GrGpu::GrGpu()
|
||||||
: f8bitPaletteSupport(false)
|
: fContext(NULL)
|
||||||
, fContext(NULL)
|
|
||||||
, fVertexPool(NULL)
|
, fVertexPool(NULL)
|
||||||
, fIndexPool(NULL)
|
, fIndexPool(NULL)
|
||||||
, fVertexPoolUseCnt(0)
|
, fVertexPoolUseCnt(0)
|
||||||
|
139
gpu/src/GrGpu.h
139
gpu/src/GrGpu.h
@ -54,6 +54,7 @@ struct GrGpuStats {
|
|||||||
class GrGpu : public GrDrawTarget {
|
class GrGpu : public GrDrawTarget {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional blend coeffecients for dual source blending, not exposed
|
* Additional blend coeffecients for dual source blending, not exposed
|
||||||
* through GrPaint/GrContext.
|
* through GrPaint/GrContext.
|
||||||
@ -146,118 +147,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
GrIndexBuffer* createIndexBuffer(uint32_t size, bool dynamic);
|
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.
|
* Returns an index buffer that can be used to render quads.
|
||||||
* Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
|
* Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
|
||||||
@ -331,6 +220,7 @@ public:
|
|||||||
|
|
||||||
// GrDrawTarget overrides
|
// GrDrawTarget overrides
|
||||||
virtual bool willUseHWAALines() const;
|
virtual bool willUseHWAALines() const;
|
||||||
|
virtual void clear(const GrIRect* rect, GrColor color);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum PrivateStateBits {
|
enum PrivateStateBits {
|
||||||
@ -363,31 +253,6 @@ protected:
|
|||||||
// and the client isn't using the stencil test.
|
// and the client isn't using the stencil test.
|
||||||
static const GrStencilSettings gClipStencilSettings;
|
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;
|
GrGpuStats fStats;
|
||||||
|
|
||||||
|
@ -257,9 +257,9 @@ static int probe_for_min_render_target_width(const GrGLInterface* gl,
|
|||||||
return minRenderTargetWidth;
|
return minRenderTargetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding) {
|
||||||
|
|
||||||
GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
|
fPrintedCaps = false;
|
||||||
: fStencilFormats(8) {
|
|
||||||
|
|
||||||
gl->ref();
|
gl->ref();
|
||||||
fGL = gl;
|
fGL = gl;
|
||||||
@ -303,241 +303,7 @@ GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
|
|||||||
|
|
||||||
this->resetDirtyFlags();
|
this->resetDirtyFlags();
|
||||||
|
|
||||||
GrGLint maxTextureUnits;
|
this->initCaps();
|
||||||
// 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);
|
|
||||||
GrAssert(maxTextureUnits > kNumStages);
|
|
||||||
}
|
|
||||||
if (kES2_GrGLBinding != this->glBinding()) {
|
|
||||||
GR_GL_GetIntegerv(gl, 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);
|
|
||||||
} else if (kDesktop_GrGLBinding != this->glBinding()) {
|
|
||||||
GrGLint max;
|
|
||||||
GR_GL_GetIntegerv(gl, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
|
|
||||||
fMaxFragmentUniformVectors = max / 4;
|
|
||||||
} else {
|
|
||||||
fMaxFragmentUniformVectors = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Check for supported features.
|
|
||||||
|
|
||||||
this->setupStencilFormats();
|
|
||||||
|
|
||||||
GrGLint numFormats;
|
|
||||||
GR_GL_GetIntegerv(gl, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
|
|
||||||
SkAutoSTMalloc<10, GrGLint> formats(numFormats);
|
|
||||||
GR_GL_GetIntegerv(gl, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
|
|
||||||
for (int i = 0; i < numFormats; ++i) {
|
|
||||||
if (formats[i] == GR_GL_PALETTE8_RGBA8) {
|
|
||||||
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");
|
|
||||||
} else {
|
|
||||||
fHasStencilWrap = (fGLVersion >= GR_GL_VER(2,0)) ||
|
|
||||||
this->hasExtension("GL_OES_stencil_wrap");
|
|
||||||
}
|
|
||||||
if (gPrintStartupSpew) {
|
|
||||||
GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
// supported on GL 1.4 and higher or by extension
|
|
||||||
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));
|
|
||||||
// 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kDesktop_GrGLBinding == this->glBinding()) {
|
|
||||||
fRGBA8Renderbuffer = true;
|
|
||||||
} else {
|
|
||||||
fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
|
|
||||||
}
|
|
||||||
if (gPrintStartupSpew) {
|
|
||||||
GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (kDesktop_GrGLBinding != this->glBinding()) {
|
|
||||||
if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
|
|
||||||
GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kDesktop_GrGLBinding == this->glBinding()) {
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
fNPOTTextureTileSupport = false;
|
|
||||||
fNPOTTextureSupport = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (fGLVersion >= GR_GL_VER(2,0)) {
|
|
||||||
fNPOTTextureSupport = true;
|
|
||||||
fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
|
|
||||||
} else {
|
|
||||||
fNPOTTextureSupport =
|
|
||||||
this->hasExtension("GL_APPLE_texture_2D_limited_npot");
|
|
||||||
fNPOTTextureTileSupport = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fAALineSupport = (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;
|
|
||||||
if (expectNPOTTargets == kProbe_GrGLCapability) {
|
|
||||||
fNPOTRenderTargetSupport =
|
|
||||||
probe_for_npot_render_target_support(gl, fNPOTTextureSupport);
|
|
||||||
} else {
|
|
||||||
GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
|
|
||||||
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);
|
|
||||||
// Our render targets are always created with textures as the color
|
|
||||||
// attachment, hence this min:
|
|
||||||
fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
|
|
||||||
|
|
||||||
fMinRenderTargetHeight = gl->fMinRenderTargetHeight;
|
|
||||||
if (fMinRenderTargetHeight == kProbe_GrGLCapability) {
|
|
||||||
fMinRenderTargetHeight =
|
|
||||||
probe_for_min_render_target_height(gl,fNPOTRenderTargetSupport,
|
|
||||||
fMaxRenderTargetSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
fMinRenderTargetWidth = gl->fMinRenderTargetWidth;
|
|
||||||
if (fMinRenderTargetWidth == kProbe_GrGLCapability) {
|
|
||||||
fMinRenderTargetWidth =
|
|
||||||
probe_for_min_render_target_width(gl, fNPOTRenderTargetSupport,
|
|
||||||
fMaxRenderTargetSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
fLastSuccessfulStencilFmtIdx = 0;
|
fLastSuccessfulStencilFmtIdx = 0;
|
||||||
}
|
}
|
||||||
@ -549,7 +315,255 @@ GrGpuGL::~GrGpuGL() {
|
|||||||
fGL->unref();
|
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(fGL, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
|
||||||
|
GrAssert(maxTextureUnits > kNumStages);
|
||||||
|
}
|
||||||
|
if (kES2_GrGLBinding != this->glBinding()) {
|
||||||
|
GR_GL_GetIntegerv(fGL, GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
|
||||||
|
GrAssert(maxTextureUnits > kNumStages);
|
||||||
|
}
|
||||||
|
if (kES2_GrGLBinding == this->glBinding()) {
|
||||||
|
GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
|
||||||
|
&fGLCaps.fMaxFragmentUniformVectors);
|
||||||
|
} else if (kDesktop_GrGLBinding != this->glBinding()) {
|
||||||
|
GrGLint max;
|
||||||
|
GR_GL_GetIntegerv(fGL, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
|
||||||
|
fGLCaps.fMaxFragmentUniformVectors = max / 4;
|
||||||
|
} else {
|
||||||
|
fGLCaps.fMaxFragmentUniformVectors = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrGLint numFormats;
|
||||||
|
GR_GL_GetIntegerv(fGL, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
|
||||||
|
SkAutoSTMalloc<10, GrGLint> formats(numFormats);
|
||||||
|
GR_GL_GetIntegerv(fGL, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
|
||||||
|
for (int i = 0; i < numFormats; ++i) {
|
||||||
|
if (formats[i] == GR_GL_PALETTE8_RGBA8) {
|
||||||
|
fCaps.f8BitPaletteSupport = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDesktop_GrGLBinding == this->glBinding()) {
|
||||||
|
fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(1,4)) ||
|
||||||
|
this->hasExtension("GL_EXT_stencil_wrap");
|
||||||
|
} else {
|
||||||
|
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).
|
||||||
|
fCaps.fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
|
||||||
|
// supported on GL 1.4 and higher or by extension
|
||||||
|
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.
|
||||||
|
fCaps.fTwoSidedStencilSupport = (fGLVersion >= GR_GL_VER(2,0));
|
||||||
|
// stencil wrap support is in ES2, ES1 requires extension.
|
||||||
|
fCaps.fStencilWrapOpsSupport = (fGLVersion >= GR_GL_VER(2,0)) ||
|
||||||
|
this->hasExtension("GL_OES_stencil_wrap");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDesktop_GrGLBinding == this->glBinding()) {
|
||||||
|
fGLCaps.fRGBA8Renderbuffer = true;
|
||||||
|
} else {
|
||||||
|
fGLCaps.fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (kDesktop_GrGLBinding != this->glBinding()) {
|
||||||
|
if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
|
||||||
|
GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDesktop_GrGLBinding == this->glBinding()) {
|
||||||
|
fCaps.fBufferLockSupport = true; // we require VBO support and the desktop VBO
|
||||||
|
// extension includes glMapBuffer.
|
||||||
|
} else {
|
||||||
|
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")) {
|
||||||
|
fCaps.fNPOTTextureTileSupport = true;
|
||||||
|
fCaps.fNPOTTextureSupport = true;
|
||||||
|
} else {
|
||||||
|
fCaps.fNPOTTextureTileSupport = false;
|
||||||
|
fCaps.fNPOTTextureSupport = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fGLVersion >= GR_GL_VER(2,0)) {
|
||||||
|
fCaps.fNPOTTextureSupport = true;
|
||||||
|
fCaps.fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
|
||||||
|
} else {
|
||||||
|
fCaps.fNPOTTextureSupport =
|
||||||
|
this->hasExtension("GL_APPLE_texture_2D_limited_npot");
|
||||||
|
fCaps.fNPOTTextureTileSupport = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = fGL->fNPOTRenderTargetSupport;
|
||||||
|
if (expectNPOTTargets == kProbe_GrGLCapability) {
|
||||||
|
fCaps.fNPOTRenderTargetSupport =
|
||||||
|
probe_for_npot_render_target_support(fGL, fCaps.fNPOTTextureSupport);
|
||||||
|
} else {
|
||||||
|
GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
|
||||||
|
fCaps.fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
fCaps.fMaxRenderTargetSize = GrMin(fCaps.fMaxTextureSize, fCaps.fMaxRenderTargetSize);
|
||||||
|
|
||||||
|
fCaps.fMinRenderTargetHeight = fGL->fMinRenderTargetHeight;
|
||||||
|
if (fCaps.fMinRenderTargetHeight == kProbe_GrGLCapability) {
|
||||||
|
fCaps.fMinRenderTargetHeight =
|
||||||
|
probe_for_min_render_target_height(fGL, fCaps.fNPOTRenderTargetSupport,
|
||||||
|
fCaps.fMaxRenderTargetSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fCaps.fMinRenderTargetWidth = fGL->fMinRenderTargetWidth;
|
||||||
|
if (fCaps.fMinRenderTargetWidth == kProbe_GrGLCapability) {
|
||||||
|
fCaps.fMinRenderTargetWidth =
|
||||||
|
probe_for_min_render_target_width(fGL, fCaps.fNPOTRenderTargetSupport,
|
||||||
|
fCaps.fMaxRenderTargetSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->initFSAASupport();
|
||||||
|
this->initStencilFormats();
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
void GrGpuGL::resetContext() {
|
||||||
|
if (gPrintStartupSpew && !fPrintedCaps) {
|
||||||
|
fPrintedCaps = true;
|
||||||
|
this->getCaps().print();
|
||||||
|
fGLCaps.print();
|
||||||
|
}
|
||||||
|
|
||||||
// We detect cases when blending is effectively off
|
// We detect cases when blending is effectively off
|
||||||
fHWBlendDisabled = false;
|
fHWBlendDisabled = false;
|
||||||
GL_CALL(Enable(GR_GL_BLEND));
|
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));
|
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, desc.fUploadByteCount));
|
||||||
if (kIndex_8_GrPixelConfig == desc.fFormat &&
|
if (kIndex_8_GrPixelConfig == desc.fFormat &&
|
||||||
supports8BitPalette()) {
|
this->getCaps().f8BitPaletteSupport) {
|
||||||
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
|
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
|
||||||
GrAssert(desc.fContentWidth == desc.fAllocWidth);
|
GrAssert(desc.fContentWidth == desc.fAllocWidth);
|
||||||
GrAssert(desc.fContentHeight == desc.fAllocHeight);
|
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
|
// If we are using multisampling we will create two FBOS. We render
|
||||||
// to one and then resolve to the texture bound to the other.
|
// 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(GenFramebuffers(1, &desc->fRTFBOID));
|
||||||
GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
|
GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
|
||||||
if (!desc->fRTFBOID ||
|
if (!desc->fRTFBOID ||
|
||||||
@ -1032,39 +986,42 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
|
|||||||
return return_null_texture();
|
return return_null_texture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Caps& caps = this->getCaps();
|
||||||
|
|
||||||
// We keep GrRenderTargets in GL's normal orientation so that they
|
// We keep GrRenderTargets in GL's normal orientation so that they
|
||||||
// can be drawn to by the outside world without the client having
|
// can be drawn to by the outside world without the client having
|
||||||
// to render upside down.
|
// to render upside down.
|
||||||
glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
|
glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
|
||||||
GrGLTexture::kTopDown_Orientation;
|
GrGLTexture::kTopDown_Orientation;
|
||||||
|
|
||||||
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
|
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fGLCaps.fAASamples));
|
||||||
glRTDesc.fSampleCnt = fAASamples[desc.fAALevel];
|
glRTDesc.fSampleCnt = fGLCaps.fAASamples[desc.fAALevel];
|
||||||
if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
|
if (GLCaps::kNone_MSFBO == fGLCaps.fMSFBOType &&
|
||||||
|
desc.fAALevel != kNone_GrAALevel) {
|
||||||
GrPrintf("AA RT requested but not supported on this platform.");
|
GrPrintf("AA RT requested but not supported on this platform.");
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
|
glTexDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
|
||||||
|
|
||||||
if (renderTarget) {
|
if (renderTarget) {
|
||||||
if (!this->npotRenderTargetSupport()) {
|
if (!caps.fNPOTRenderTargetSupport) {
|
||||||
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
|
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
|
||||||
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
|
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
|
glTexDesc.fAllocWidth = GrMax(caps.fMinRenderTargetWidth,
|
||||||
glTexDesc.fAllocWidth);
|
glTexDesc.fAllocWidth);
|
||||||
glTexDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
|
glTexDesc.fAllocHeight = GrMax(caps.fMinRenderTargetHeight,
|
||||||
glTexDesc.fAllocHeight);
|
glTexDesc.fAllocHeight);
|
||||||
if (glTexDesc.fAllocWidth > fMaxRenderTargetSize ||
|
if (glTexDesc.fAllocWidth > caps.fMaxRenderTargetSize ||
|
||||||
glTexDesc.fAllocHeight > fMaxRenderTargetSize) {
|
glTexDesc.fAllocHeight > caps.fMaxRenderTargetSize) {
|
||||||
return return_null_texture();
|
return return_null_texture();
|
||||||
}
|
}
|
||||||
} else if (!this->npotTextureSupport()) {
|
} else if (!caps.fNPOTTextureSupport) {
|
||||||
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
|
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
|
||||||
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
|
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
|
||||||
if (glTexDesc.fAllocWidth > fMaxTextureSize ||
|
if (glTexDesc.fAllocWidth > caps.fMaxTextureSize ||
|
||||||
glTexDesc.fAllocHeight > fMaxTextureSize) {
|
glTexDesc.fAllocHeight > caps.fMaxTextureSize) {
|
||||||
return return_null_texture();
|
return return_null_texture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1156,13 +1113,14 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
|
|||||||
|
|
||||||
GrGLStencilBuffer* sb = NULL;
|
GrGLStencilBuffer* sb = NULL;
|
||||||
|
|
||||||
int stencilFmtCnt = fStencilFormats.count();
|
int stencilFmtCnt = fGLCaps.fStencilFormats.count();
|
||||||
for (int i = 0; i < stencilFmtCnt; ++i) {
|
for (int i = 0; i < stencilFmtCnt; ++i) {
|
||||||
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
|
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
|
||||||
// we start with the last stencil format that succeeded in hopes
|
// we start with the last stencil format that succeeded in hopes
|
||||||
// that we won't go through this loop more than once after the
|
// that we won't go through this loop more than once after the
|
||||||
// first (painful) stencil creation.
|
// first (painful) stencil creation.
|
||||||
int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
|
int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
|
||||||
|
const GrGLStencilBuffer::Format& sFmt = fGLCaps.fStencilFormats[sIdx];
|
||||||
// we do this "if" so that we don't call the multisample
|
// we do this "if" so that we don't call the multisample
|
||||||
// version on a GL that doesn't have an MSAA extension.
|
// version on a GL that doesn't have an MSAA extension.
|
||||||
if (samples > 1) {
|
if (samples > 1) {
|
||||||
@ -1170,13 +1128,13 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
|
|||||||
RenderbufferStorageMultisample(
|
RenderbufferStorageMultisample(
|
||||||
GR_GL_RENDERBUFFER,
|
GR_GL_RENDERBUFFER,
|
||||||
samples,
|
samples,
|
||||||
fStencilFormats[sIdx].fInternalFormat,
|
sFmt.fInternalFormat,
|
||||||
width,
|
width,
|
||||||
height));
|
height));
|
||||||
} else {
|
} else {
|
||||||
GR_GL_CALL_NOERRCHECK(this->glInterface(),
|
GR_GL_CALL_NOERRCHECK(this->glInterface(),
|
||||||
RenderbufferStorage(GR_GL_RENDERBUFFER,
|
RenderbufferStorage(GR_GL_RENDERBUFFER,
|
||||||
fStencilFormats[sIdx].fInternalFormat,
|
sFmt.fInternalFormat,
|
||||||
width, height));
|
width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1184,7 +1142,7 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
|
|||||||
if (err == GR_GL_NO_ERROR) {
|
if (err == GR_GL_NO_ERROR) {
|
||||||
// After sized formats we attempt an unsized format and take whatever
|
// After sized formats we attempt an unsized format and take whatever
|
||||||
// sizes GL gives us. In that case we query for the size.
|
// 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);
|
get_stencil_rb_sizes(this->glInterface(), sbID, &format);
|
||||||
sb = new GrGLStencilBuffer(this, sbID, width, height,
|
sb = new GrGLStencilBuffer(this, sbID, width, height,
|
||||||
samples, format);
|
samples, format);
|
||||||
@ -1606,7 +1564,7 @@ void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
|
|||||||
void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
|
void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
|
||||||
|
|
||||||
if (rt->needsResolve()) {
|
if (rt->needsResolve()) {
|
||||||
GrAssert(kNone_MSFBO != fMSFBOType);
|
GrAssert(GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType);
|
||||||
GrAssert(rt->textureFBOID() != rt->renderFBOID());
|
GrAssert(rt->textureFBOID() != rt->renderFBOID());
|
||||||
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
|
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
|
||||||
rt->renderFBOID()));
|
rt->renderFBOID()));
|
||||||
@ -1624,7 +1582,7 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
|
|||||||
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
|
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
|
||||||
dirtyRect.width(), dirtyRect.height());
|
dirtyRect.width(), dirtyRect.height());
|
||||||
|
|
||||||
if (kAppleES_MSFBO == fMSFBOType) {
|
if (GLCaps::kAppleES_MSFBO == fGLCaps.fMSFBOType) {
|
||||||
// Apple's extension uses the scissor as the blit bounds.
|
// Apple's extension uses the scissor as the blit bounds.
|
||||||
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
|
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
|
||||||
GL_CALL(Scissor(r.fLeft, r.fBottom,
|
GL_CALL(Scissor(r.fLeft, r.fBottom,
|
||||||
@ -1633,10 +1591,10 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
|
|||||||
fHWBounds.fScissorRect.invalidate();
|
fHWBounds.fScissorRect.invalidate();
|
||||||
fHWBounds.fScissorEnabled = true;
|
fHWBounds.fScissorEnabled = true;
|
||||||
} else {
|
} else {
|
||||||
if (kDesktopARB_MSFBO != fMSFBOType) {
|
if (GLCaps::kDesktopARB_MSFBO != fGLCaps.fMSFBOType) {
|
||||||
// this respects the scissor during the blit, so disable it.
|
// this respects the scissor during the blit, so disable it.
|
||||||
GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
|
GrAssert(GLCaps::kDesktopEXT_MSFBO == fGLCaps.fMSFBOType);
|
||||||
flushScissor(NULL);
|
this->flushScissor(NULL);
|
||||||
}
|
}
|
||||||
int right = r.fLeft + r.fWidth;
|
int right = r.fLeft + r.fWidth;
|
||||||
int top = r.fBottom + r.fHeight;
|
int top = r.fBottom + r.fHeight;
|
||||||
@ -1716,7 +1674,7 @@ void GrGpuGL::flushStencil() {
|
|||||||
} else {
|
} else {
|
||||||
GL_CALL(Enable(GR_GL_STENCIL_TEST));
|
GL_CALL(Enable(GR_GL_STENCIL_TEST));
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
if (!fStencilWrapOpsSupport) {
|
if (!this->getCaps().fStencilWrapOpsSupport) {
|
||||||
GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
|
GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
|
||||||
GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
|
GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
|
||||||
GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
|
GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
|
||||||
@ -1768,7 +1726,7 @@ void GrGpuGL::flushStencil() {
|
|||||||
(unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
|
(unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
|
||||||
GrAssert(settings->fBackPassOp >= 0 &&
|
GrAssert(settings->fBackPassOp >= 0 &&
|
||||||
(unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
|
(unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
|
||||||
if (fTwoSidedStencilSupport) {
|
if (this->getCaps().fTwoSidedStencilSupport) {
|
||||||
GrGLenum backFunc;
|
GrGLenum backFunc;
|
||||||
|
|
||||||
unsigned int backRef = settings->fBackFuncRef;
|
unsigned int backRef = settings->fBackFuncRef;
|
||||||
@ -2133,7 +2091,7 @@ bool GrGpuGL::canBeTexture(GrPixelConfig config,
|
|||||||
*type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
|
*type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
|
||||||
break;
|
break;
|
||||||
case kIndex_8_GrPixelConfig:
|
case kIndex_8_GrPixelConfig:
|
||||||
if (this->supports8BitPalette()) {
|
if (this->getCaps().f8BitPaletteSupport) {
|
||||||
*format = GR_GL_PALETTE8_RGBA8;
|
*format = GR_GL_PALETTE8_RGBA8;
|
||||||
*internalFormat = GR_GL_PALETTE8_RGBA8;
|
*internalFormat = GR_GL_PALETTE8_RGBA8;
|
||||||
*type = GR_GL_UNSIGNED_BYTE; // unused I think
|
*type = GR_GL_UNSIGNED_BYTE; // unused I think
|
||||||
@ -2177,7 +2135,7 @@ bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
|
|||||||
switch (config) {
|
switch (config) {
|
||||||
case kRGBA_8888_GrPixelConfig:
|
case kRGBA_8888_GrPixelConfig:
|
||||||
case kRGBX_8888_GrPixelConfig:
|
case kRGBX_8888_GrPixelConfig:
|
||||||
if (fRGBA8Renderbuffer) {
|
if (fGLCaps.fRGBA8Renderbuffer) {
|
||||||
*format = GR_GL_RGBA8;
|
*format = GR_GL_RGBA8;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -2267,6 +2225,32 @@ void GrGpuGL::setBuffers(bool indexed,
|
|||||||
int GrGpuGL::getMaxEdges() const {
|
int GrGpuGL::getMaxEdges() const {
|
||||||
// FIXME: This is a pessimistic estimate based on how many other things
|
// FIXME: This is a pessimistic estimate based on how many other things
|
||||||
// want to add uniforms. This should be centralized somewhere.
|
// 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"));
|
||||||
|
}
|
||||||
|
@ -146,9 +146,14 @@ protected:
|
|||||||
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
|
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Inits GrDrawTarget::Caps and GLCaps, sublcass may enable
|
||||||
|
// additional caps.
|
||||||
|
void initCaps();
|
||||||
|
|
||||||
|
void initFSAASupport();
|
||||||
|
|
||||||
// determines valid stencil formats
|
// determines valid stencil formats
|
||||||
void setupStencilFormats();
|
void initStencilFormats();
|
||||||
|
|
||||||
// notify callbacks to update state tracking when related
|
// notify callbacks to update state tracking when related
|
||||||
// objects are bound to GL or deleted outside of the class
|
// objects are bound to GL or deleted outside of the class
|
||||||
@ -194,24 +199,32 @@ private:
|
|||||||
SkString fExtensionString;
|
SkString fExtensionString;
|
||||||
GrGLVersion fGLVersion;
|
GrGLVersion fGLVersion;
|
||||||
|
|
||||||
|
struct GLCaps {
|
||||||
|
// prealloc space for 8 stencil formats
|
||||||
|
GLCaps() : fStencilFormats(8) {}
|
||||||
SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
|
SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
|
||||||
// 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.
|
|
||||||
GrGLuint fStencilClearFBO;
|
|
||||||
|
|
||||||
bool fHWBlendDisabled;
|
|
||||||
|
|
||||||
GrGLuint fAASamples[4];
|
|
||||||
enum {
|
enum {
|
||||||
kNone_MSFBO = 0, //<! no support for MSAA FBOs
|
/**
|
||||||
kDesktopARB_MSFBO,//<! GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
|
* no support for MSAA FBOs
|
||||||
kDesktopEXT_MSFBO,//<! earlier GL_EXT_framebuffer* extensions
|
*/
|
||||||
kAppleES_MSFBO, //<! GL_APPLE_framebuffer_multisample ES extension
|
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;
|
} fMSFBOType;
|
||||||
|
|
||||||
// Do we have stencil wrap ops.
|
// TODO: get rid of GrAALevel and use sample cnt directly
|
||||||
bool fHasStencilWrap;
|
GrGLuint fAASamples[4];
|
||||||
|
|
||||||
// The maximum number of fragment uniform vectors (GLES has min. 16).
|
// The maximum number of fragment uniform vectors (GLES has min. 16).
|
||||||
int fMaxFragmentUniformVectors;
|
int fMaxFragmentUniformVectors;
|
||||||
@ -219,6 +232,17 @@ private:
|
|||||||
// ES requires an extension to support RGBA8 in RenderBufferStorage
|
// ES requires an extension to support RGBA8 in RenderBufferStorage
|
||||||
bool fRGBA8Renderbuffer;
|
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.
|
||||||
|
GrGLuint fStencilClearFBO;
|
||||||
|
|
||||||
|
bool fHWBlendDisabled;
|
||||||
|
|
||||||
int fActiveTextureUnitIdx;
|
int fActiveTextureUnitIdx;
|
||||||
|
|
||||||
// we record what stencil format worked last time to hopefully exit early
|
// we record what stencil format worked last time to hopefully exit early
|
||||||
@ -228,6 +252,8 @@ private:
|
|||||||
const GrGLInterface* fGL;
|
const GrGLInterface* fGL;
|
||||||
GrGLBinding fGLBinding;
|
GrGLBinding fGLBinding;
|
||||||
|
|
||||||
|
bool fPrintedCaps;
|
||||||
|
|
||||||
typedef GrGpu INHERITED;
|
typedef GrGpu INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,9 +62,6 @@ GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
|
|||||||
|
|
||||||
GrGpuGLFixed::GrGpuGLFixed(const GrGLInterface* gl)
|
GrGpuGLFixed::GrGpuGLFixed(const GrGLInterface* gl)
|
||||||
: GrGpuGL(gl, get_binding_in_use(gl)) {
|
: GrGpuGL(gl, get_binding_in_use(gl)) {
|
||||||
fShaderSupport = false;
|
|
||||||
fShaderDerivativeSupport = false;
|
|
||||||
fDualSourceBlendingSupport = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGpuGLFixed::~GrGpuGLFixed() {
|
GrGpuGLFixed::~GrGpuGLFixed() {
|
||||||
|
@ -213,7 +213,7 @@ bool GrGpuGLShaders::programUnitTest() {
|
|||||||
bool vertexEdgeAA = random.nextF() > .5f;
|
bool vertexEdgeAA = random.nextF() > .5f;
|
||||||
if (vertexEdgeAA) {
|
if (vertexEdgeAA) {
|
||||||
pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit;
|
pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit;
|
||||||
if (this->supportsShaderDerivatives()) {
|
if (this->getCaps().fShaderDerivativeSupport) {
|
||||||
pdesc.fVertexEdgeType = random.nextF() > 0.5f ?
|
pdesc.fVertexEdgeType = random.nextF() > 0.5f ?
|
||||||
kHairQuad_EdgeType :
|
kHairQuad_EdgeType :
|
||||||
kHairLine_EdgeType;
|
kHairLine_EdgeType;
|
||||||
@ -229,7 +229,7 @@ bool GrGpuGLShaders::programUnitTest() {
|
|||||||
pdesc.fEdgeAANumEdges = 0;
|
pdesc.fEdgeAANumEdges = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fDualSourceBlendingSupport) {
|
if (this->getCaps().fDualSourceBlendingSupport) {
|
||||||
pdesc.fDualSrcOutput =
|
pdesc.fDualSrcOutput =
|
||||||
(ProgramDesc::DualSrcOutput)
|
(ProgramDesc::DualSrcOutput)
|
||||||
(int)(random.nextF() * ProgramDesc::kDualSrcOutputCnt);
|
(int)(random.nextF() * ProgramDesc::kDualSrcOutputCnt);
|
||||||
@ -290,15 +290,15 @@ GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
|
|||||||
GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
|
GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl)
|
||||||
: GrGpuGL(gl, get_binding_in_use(gl)) {
|
: GrGpuGL(gl, get_binding_in_use(gl)) {
|
||||||
|
|
||||||
fShaderSupport = true;
|
fCaps.fShaderSupport = true;
|
||||||
if (kDesktop_GrGLBinding == this->glBinding()) {
|
if (kDesktop_GrGLBinding == this->glBinding()) {
|
||||||
fDualSourceBlendingSupport =
|
fCaps.fDualSourceBlendingSupport =
|
||||||
this->glVersion() >= GR_GL_VER(3,3) ||
|
this->glVersion() >= GR_GL_VER(3,3) ||
|
||||||
this->hasExtension("GL_ARB_blend_func_extended");
|
this->hasExtension("GL_ARB_blend_func_extended");
|
||||||
fShaderDerivativeSupport = true;
|
fCaps.fShaderDerivativeSupport = true;
|
||||||
} else {
|
} else {
|
||||||
fDualSourceBlendingSupport = false;
|
fCaps.fDualSourceBlendingSupport = false;
|
||||||
fShaderDerivativeSupport =
|
fCaps.fShaderDerivativeSupport =
|
||||||
this->hasExtension("GL_OES_standard_derivatives");
|
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
|
// (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
|
// the dst coeff be kISA. Or solid draw with kSA can be tweaked to be
|
||||||
// kOne).
|
// kOne).
|
||||||
if (fDualSourceBlendingSupport) {
|
if (this->getCaps().fDualSourceBlendingSupport) {
|
||||||
if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
|
if (kZero_BlendCoeff == fCurrDrawState.fDstBlend) {
|
||||||
// write the coverage value to second color
|
// write the coverage value to second color
|
||||||
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
|
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
|
GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
|
||||||
GrVertexBufferAllocPool* vertexPool,
|
GrVertexBufferAllocPool* vertexPool,
|
||||||
GrIndexBufferAllocPool* indexPool)
|
GrIndexBufferAllocPool* indexPool)
|
||||||
: fGpu(gpu)
|
: fDraws(&fDrawStorage)
|
||||||
, fDraws(&fDrawStorage)
|
|
||||||
, fStates(&fStateStorage)
|
, fStates(&fStateStorage)
|
||||||
, fClears(&fClearStorage)
|
, fClears(&fClearStorage)
|
||||||
, fClips(&fClipStorage)
|
, fClips(&fClipStorage)
|
||||||
@ -34,11 +33,11 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
|
|||||||
, fIndexPool(*indexPool)
|
, fIndexPool(*indexPool)
|
||||||
, fGeoPoolStateStack(&fGeoStackStorage) {
|
, fGeoPoolStateStack(&fGeoStackStorage) {
|
||||||
|
|
||||||
|
fCaps = gpu->getCaps();
|
||||||
|
|
||||||
GrAssert(NULL != vertexPool);
|
GrAssert(NULL != vertexPool);
|
||||||
GrAssert(NULL != indexPool);
|
GrAssert(NULL != indexPool);
|
||||||
|
|
||||||
gpu->ref();
|
|
||||||
|
|
||||||
GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
|
GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
|
||||||
poolState.fUsedPoolVertexBytes = 0;
|
poolState.fUsedPoolVertexBytes = 0;
|
||||||
poolState.fUsedPoolIndexBytes = 0;
|
poolState.fUsedPoolIndexBytes = 0;
|
||||||
@ -53,7 +52,6 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
|
|||||||
GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
|
GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
|
||||||
this->reset();
|
this->reset();
|
||||||
GrSafeUnref(fQuadIndexBuffer);
|
GrSafeUnref(fQuadIndexBuffer);
|
||||||
fGpu->unref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
|
void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
|
||||||
@ -627,7 +625,7 @@ void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GrInOrderDrawBuffer::willUseHWAALines() const {
|
bool GrInOrderDrawBuffer::willUseHWAALines() const {
|
||||||
return fGpu->supportsHWAALines() &&
|
return this->getCaps().fHWAALineSupport &&
|
||||||
CanUseHWAALines(this->getGeomSrc().fVertexLayout, fCurrDrawState);
|
CanUseHWAALines(this->getGeomSrc().fVertexLayout, fCurrDrawState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +57,9 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrDrawTarget* target,
|
|||||||
void GrPathRendererChain::init() {
|
void GrPathRendererChain::init() {
|
||||||
GrAssert(!fInit);
|
GrAssert(!fInit);
|
||||||
GrGpu* gpu = fOwner->getGpu();
|
GrGpu* gpu = fOwner->getGpu();
|
||||||
this->addPathRenderer(
|
bool twoSided = gpu->getCaps().fTwoSidedStencilSupport;
|
||||||
new GrDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
|
bool wrapOp = gpu->getCaps().fStencilWrapOpsSupport;
|
||||||
gpu->supportsStencilWrapOps()))->unref();
|
this->addPathRenderer(new GrDefaultPathRenderer(twoSided, wrapOp))->unref();
|
||||||
GrPathRenderer::AddPathRenderers(fOwner, fFlags, this);
|
GrPathRenderer::AddPathRenderers(fOwner, fFlags, this);
|
||||||
fInit = true;
|
fInit = true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user