cleanup GrGLTexture / GrGLRenderTarget cons. Make GrRenderTarget aware of its msaa sample count.

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



git-svn-id: http://skia.googlecode.com/svn/trunk@1996 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-07-29 20:29:05 +00:00
parent aa5b6730f2
commit 5bfc21761e
10 changed files with 295 additions and 205 deletions

View File

@ -77,7 +77,12 @@ public:
/**
* @return true if the render target is multisampled, false otherwise
*/
bool isMultisampled() { return fIsMultisampled; }
bool isMultisampled() const { return 0 != fSampleCnt; }
/**
* @return the number of samples-per-pixel or zero if non-MSAA.
*/
int numSamples() const { return fSampleCnt; }
/**
* Call to indicate the multisample contents were modified such that the
@ -147,14 +152,14 @@ protected:
int height,
GrPixelConfig config,
int stencilBits,
bool isMultisampled)
int sampleCnt)
: INHERITED(gpu)
, fTexture(texture)
, fWidth(width)
, fHeight(height)
, fConfig(config)
, fStencilBits(stencilBits)
, fIsMultisampled(isMultisampled)
, fSampleCnt(sampleCnt)
{
fResolveRect.setLargestInverted();
}
@ -176,7 +181,7 @@ private:
int fHeight;
GrPixelConfig fConfig;
int fStencilBits;
bool fIsMultisampled;
int fSampleCnt;
GrIRect fResolveRect;
// GrGpu keeps a cached clip in the render target to avoid redundantly

View File

@ -506,10 +506,14 @@ enum GrPlatformSurfaceType {
enum GrPlatformRenderTargetFlags {
kNone_GrPlatformRenderTargetFlagBit = 0x0,
/**
* Specifies that the object being created is multisampled.
* WILL BE REMOVED ONCE WEBKIT STOPS USING THIS. INSTEAD
* SPECIFY # OF SAMPLES IN GrPlatformSurfaceDesc::fSampleCnt
*/
kIsMultisampled_GrPlatformRenderTargetFlagBit = 0x1,
/**
* Gives permission to Gr to perform the downsample-resolve of a
* multisampled render target. If this is not set then read pixel
@ -545,6 +549,13 @@ struct GrPlatformSurfaceDesc {
* set in fFlags.
*/
int fStencilBits;
/**
* Number of samples per-pixel. Only relevant if kIsRenderTarget is set in
* fFlags.
*/
int fSampleCnt;
/**
* Texture object in 3D API. Only relevant if fSurfaceType is kTexture or
* kTextureRenderTarget.
@ -600,11 +611,12 @@ struct GrPlatformSurfaceDesc {
*
* GrPlatformSurfaceDesc renderTargetTextureDesc;
* renderTargetTextureDesc.fSurfaceType = kTextureRenderTarget_GrPlatformSurfaceType;
* renderTargetTextureDesc.fRenderTargetFlags = (kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit);
* renderTargetTextureDesc.fRenderTargetFlags = kGrCanResolve_GrPlatformRenderTargetFlagBit;
* renderTargetTextureDesc.fWidth = W;
* renderTargetTextureDesc.fHeight = H;
* renderTargetTextureDesc.fConfig = kRGBA_8888_GrPixelConfig
* renderTargetTextureDesc.fStencilBits = 8;
* renderTargetTextureDesc.fSampleCnt = S;
* renderTargetTextureDesc.fPlatformTexture = textureID;
* renderTargetTextureDesc.fPlatformRenderTarget = drawFBOID;
* renderTargetTextureDesc.fPlatformResolveDestination = readFBOID;

View File

@ -465,6 +465,7 @@ GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc)
0 != desc.fRenderTargetFlags) {
return NULL;
}
#if GR_USE_PLATFORM_CREATE_SAMPLE_COUNT
if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
@ -474,6 +475,17 @@ GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc)
!(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
}
#else
if (desc.fSampleCnt &&
(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
}
if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
desc.fSampleCnt &&
!(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
return NULL;
}
#endif
return fGpu->createPlatformSurface(desc);
}

View File

@ -13,27 +13,44 @@
#define GPUGL static_cast<GrGpuGL*>(getGpu())
GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
const GLRenderTargetIDs& ids,
GrGLTexID* texID,
GrPixelConfig config,
GrGLuint stencilBits,
bool isMultisampled,
const GrGLIRect& viewport,
GrGLTexture* texture)
: INHERITED(gpu, texture, viewport.fWidth,
viewport.fHeight, config,
stencilBits, isMultisampled) {
fRTFBOID = ids.fRTFBOID;
fTexFBOID = ids.fTexFBOID;
fStencilRenderbufferID = ids.fStencilRenderbufferID;
fMSColorRenderbufferID = ids.fMSColorRenderbufferID;
void GrGLRenderTarget::init(const Desc& desc,
const GrGLIRect& viewport,
GrGLTexID* texID) {
fRTFBOID = desc.fRTFBOID;
fTexFBOID = desc.fTexFBOID;
fMSColorRenderbufferID = desc.fMSColorRenderbufferID;
fStencilRenderbufferID = desc.fStencilRenderbufferID;
fViewport = viewport;
fOwnIDs = ids.fOwnIDs;
fOwnIDs = desc.fOwnIDs;
fTexIDObj = texID;
GrSafeRef(fTexIDObj);
}
GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
const Desc& desc,
const GrGLIRect& viewport,
GrGLTexID* texID,
GrGLTexture* texture)
: INHERITED(gpu, texture, viewport.fWidth,
viewport.fHeight, desc.fConfig,
desc.fStencilBits, desc.fSampleCnt) {
GrAssert(NULL != texID);
GrAssert(NULL != texture);
// FBO 0 can't also be a texture, right?
GrAssert(0 != desc.fRTFBOID);
GrAssert(0 != desc.fTexFBOID);
this->init(desc, viewport, texID);
}
GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
const Desc& desc,
const GrGLIRect& viewport)
: INHERITED(gpu, NULL, viewport.fWidth,
viewport.fHeight, desc.fConfig,
desc.fStencilBits, desc.fSampleCnt) {
this->init(desc, viewport, NULL);
}
void GrGLRenderTarget::onRelease() {
GPUGL->notifyRenderTargetDelete(this);
if (fOwnIDs) {

View File

@ -25,23 +25,28 @@ public:
// Gr doesn't know how to resolve it.
enum { kUnresolvableFBOID = 0 };
struct GLRenderTargetIDs {
struct Desc {
GrGLuint fRTFBOID;
GrGLuint fTexFBOID;
GrGLuint fStencilRenderbufferID;
GrGLuint fMSColorRenderbufferID;
bool fOwnIDs;
void reset() { memset(this, 0, sizeof(GLRenderTargetIDs)); }
GrPixelConfig fConfig;
int fStencilBits;
int fSampleCnt;
};
GrGLRenderTarget(GrGpuGL* gpu,
const GLRenderTargetIDs& ids,
GrGLTexID* texID,
GrPixelConfig config,
GrGLuint stencilBits,
bool isMultisampled,
const GrGLIRect& fViewport,
GrGLTexture* texture);
// creates a GrGLRenderTarget associated with a texture
GrGLRenderTarget(GrGpuGL* gpu,
const Desc& desc,
const GrGLIRect& viewport,
GrGLTexID* texID,
GrGLTexture* texture);
// creates an independent GrGLRenderTarget
GrGLRenderTarget(GrGpuGL* gpu,
const Desc& desc,
const GrGLIRect& viewport);
virtual ~GrGLRenderTarget() { this->release(); }
@ -97,6 +102,8 @@ private:
// non-NULL if this RT was created by Gr with an associated GrGLTexture.
GrGLTexID* fTexIDObj;
void init(const Desc& desc, const GrGLIRect& viewport, GrGLTexID* texID);
typedef GrRenderTarget INHERITED;
};

View File

@ -33,14 +33,12 @@ const GrGLenum* GrGLTexture::WrapMode2GLWrap() {
}
};
GrGLTexture::GrGLTexture(GrGpuGL* gpu,
const GLTextureDesc& textureDesc,
const GLRenderTargetIDs& rtIDs,
const TexParams& initialTexParams)
: INHERITED(gpu,
textureDesc.fContentWidth,
textureDesc.fContentHeight,
textureDesc.fFormat) {
void GrGLTexture::init(GrGpuGL* gpu,
const Desc& textureDesc,
const GrGLRenderTarget::Desc* rtDesc,
const TexParams& initialTexParams) {
GrAssert(0 != textureDesc.fTextureID);
fTexParams = initialTexParams;
fTexIDObj = new GrGLTexID(textureDesc.fTextureID,
@ -56,9 +54,7 @@ GrGLTexture::GrGLTexture(GrGpuGL* gpu,
fScaleY = GrIntToScalar(textureDesc.fContentHeight) /
textureDesc.fAllocHeight;
GrAssert(0 != textureDesc.fTextureID);
if (rtIDs.fTexFBOID) {
if (NULL != rtDesc) {
// we render to the top left
GrGLIRect vp;
vp.fLeft = 0;
@ -66,14 +62,31 @@ GrGLTexture::GrGLTexture(GrGpuGL* gpu,
vp.fHeight = textureDesc.fContentHeight;
vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
fRenderTarget = new GrGLRenderTarget(gpu, rtIDs, fTexIDObj,
textureDesc.fFormat,
textureDesc.fStencilBits,
rtIDs.fRTFBOID != rtIDs.fTexFBOID,
vp, this);
fRenderTarget = new GrGLRenderTarget(gpu, *rtDesc, vp, fTexIDObj, this);
}
}
GrGLTexture::GrGLTexture(GrGpuGL* gpu,
const Desc& textureDesc,
const TexParams& initialTexParams)
: INHERITED(gpu,
textureDesc.fContentWidth,
textureDesc.fContentHeight,
textureDesc.fFormat) {
this->init(gpu, textureDesc, NULL, initialTexParams);
}
GrGLTexture::GrGLTexture(GrGpuGL* gpu,
const Desc& textureDesc,
const GrGLRenderTarget::Desc& rtDesc,
const TexParams& initialTexParams)
: INHERITED(gpu,
textureDesc.fContentWidth,
textureDesc.fContentHeight,
textureDesc.fFormat) {
this->init(gpu, textureDesc, &rtDesc, initialTexParams);
}
void GrGLTexture::onRelease() {
INHERITED::onRelease();
GPUGL->notifyTextureDelete(this);

View File

@ -54,7 +54,7 @@ public:
void invalidate() { memset(this, 0xff, sizeof(TexParams)); }
};
struct GLTextureDesc {
struct Desc {
int fContentWidth;
int fContentHeight;
int fAllocWidth;
@ -65,17 +65,21 @@ public:
GrGLenum fUploadFormat;
GrGLenum fUploadByteCount;
GrGLenum fUploadType;
GrGLuint fStencilBits;
Orientation fOrientation;
};
typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs;
// creates a texture that is also an RT
GrGLTexture(GrGpuGL* gpu,
const GLTextureDesc& textureDesc,
const GLRenderTargetIDs& rtIDs,
const Desc& textureDesc,
const GrGLRenderTarget::Desc& rtDesc,
const TexParams& initialTexParams);
// creates a non-RT texture
GrGLTexture(GrGpuGL* gpu,
const Desc& textureDesc,
const TexParams& initialTexParams);
virtual ~GrGLTexture() { this->release(); }
// overrides of GrTexture
@ -150,6 +154,11 @@ private:
GrScalar fScaleY;
Orientation fOrientation;
void init(GrGpuGL* gpu,
const Desc& textureDesc,
const GrGLRenderTarget::Desc* rtDesc,
const TexParams& initialTexParams);
typedef GrTexture INHERITED;
};

View File

@ -597,31 +597,45 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
GrGLRenderTarget::Desc rtDesc;
if (isRenderTarget) {
rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
rtDesc.fRTFBOID = desc.fPlatformRenderTarget;
#if GR_USE_PLATFORM_CREATE_SAMPLE_COUNT
if (desc.fSampleCnt) {
#else
if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
#endif
if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
rtDesc.fTexFBOID = desc.fPlatformResolveDestination;
} else {
GrAssert(!isTexture); // this should have been filtered by GrContext
rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
rtDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
}
} else {
rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
rtDesc.fTexFBOID = desc.fPlatformRenderTarget;
}
// we don't know what the RB ids are without glGets and we don't care
// since we aren't responsible for deleting them.
rtIDs.fStencilRenderbufferID = 0;
rtIDs.fMSColorRenderbufferID = 0;
rtIDs.fOwnIDs = false;
} else {
rtIDs.reset();
rtDesc.fStencilRenderbufferID = 0;
rtDesc.fMSColorRenderbufferID = 0;
#if GR_USE_PLATFORM_CREATE_SAMPLE_COUNT
rtDesc.fSampleCnt = desc.fSampleCnt;
#else
if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
// just guess, this code path is only compiled in WK and we aren't
// using MSAA anyway. This will be stripped out soon when WK sets
// the fSampleCnt in GrPlatformSurfaceDesc.
rtDesc.fSampleCnt = 4;
} else {
rtDesc.fSampleCnt = 0;
}
#endif
rtDesc.fStencilBits = desc.fStencilBits;
rtDesc.fOwnIDs = false;
}
if (isTexture) {
GrGLTexture::GLTextureDesc texDesc;
GrGLTexture::Desc texDesc;
GrGLenum dontCare;
if (!canBeTexture(desc.fConfig, &dontCare,
&texDesc.fUploadFormat,
@ -636,14 +650,16 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
texDesc.fFormat = desc.fConfig;
texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
texDesc.fStencilBits = desc.fStencilBits;
texDesc.fTextureID = desc.fPlatformTexture;
texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
texDesc.fOwnsID = false;
params.invalidate(); // rather than do glGets.
return new GrGLTexture(this, texDesc, rtIDs, params);
if (isRenderTarget) {
return new GrGLTexture(this, texDesc, rtDesc, params);
} else {
return new GrGLTexture(this, texDesc, params);
}
} else {
GrGLIRect viewport;
viewport.fLeft = 0;
@ -651,11 +667,7 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
viewport.fWidth = desc.fWidth;
viewport.fHeight = desc.fHeight;
bool isMSAA = kIsMultisampled_GrPlatformRenderTargetFlagBit &
desc.fRenderTargetFlags;
return new GrGLRenderTarget(this, rtIDs, NULL, desc.fConfig,
desc.fStencilBits, isMSAA, viewport, NULL);
return new GrGLRenderTarget(this, rtDesc, viewport);
}
}
@ -799,37 +811,34 @@ int get_fbo_stencil_bits(bool arbFBOExtension) {
GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
GrGLRenderTarget::Desc rtDesc;
GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
rtIDs.fTexFBOID = rtIDs.fRTFBOID;
rtIDs.fMSColorRenderbufferID = 0;
rtIDs.fStencilRenderbufferID = 0;
GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtDesc.fRTFBOID);
rtDesc.fTexFBOID = rtDesc.fRTFBOID;
rtDesc.fMSColorRenderbufferID = 0;
rtDesc.fStencilRenderbufferID = 0;
bool arbFBO = (GR_GL_SUPPORT_DESKTOP && (fGLVersion > 3.0 ||
this->hasExtension("GL_ARB_framebuffer_object")));
GrGLIRect viewport;
viewport.setFromGLViewport();
int stencilBits = get_fbo_stencil_bits(arbFBO);
rtDesc.fStencilBits = get_fbo_stencil_bits(arbFBO);
GrPixelConfig config;
GrGLint samples;
GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
GR_GL_GetIntegerv(GR_GL_SAMPLES, &rtDesc.fSampleCnt);
GrGLenum fmat = get_fbo_color_format();
if (kUnknownGLFormat == fmat) {
config = get_implied_color_config(arbFBO);
rtDesc.fConfig = get_implied_color_config(arbFBO);
} else {
config = internal_color_format_to_config(fmat);
rtDesc.fConfig = internal_color_format_to_config(fmat);
}
// may have to bind a texture to gets its format
this->setSpareTextureUnit();
rtIDs.fOwnIDs = false;
rtDesc.fOwnIDs = false;
return new GrGLRenderTarget(this, rtIDs, NULL, config, stencilBits,
(samples > 0), viewport, NULL);
return new GrGLRenderTarget(this, rtDesc, viewport);
}
///////////////////////////////////////////////////////////////////////////////
@ -916,29 +925,28 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GR_GL_CLAMP_TO_EDGE
};
GrGLTexture::GLTextureDesc glDesc;
GrGLTexture::Desc glTexDesc;
GrGLenum internalFormat;
glDesc.fContentWidth = desc.fWidth;
glDesc.fContentHeight = desc.fHeight;
glDesc.fAllocWidth = desc.fWidth;
glDesc.fAllocHeight = desc.fHeight;
glDesc.fStencilBits = 0;
glDesc.fFormat = desc.fFormat;
glDesc.fOwnsID = true;
glTexDesc.fContentWidth = desc.fWidth;
glTexDesc.fContentHeight = desc.fHeight;
glTexDesc.fAllocWidth = desc.fWidth;
glTexDesc.fAllocHeight = desc.fHeight;
glTexDesc.fFormat = desc.fFormat;
glTexDesc.fOwnsID = true;
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
if (!canBeTexture(desc.fFormat,
&internalFormat,
&glDesc.fUploadFormat,
&glDesc.fUploadType)) {
&glTexDesc.fUploadFormat,
&glTexDesc.fUploadType)) {
return return_null_texture();
}
// 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.
glDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
glTexDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
GrGLTexture::kTopDown_Orientation;
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
@ -947,13 +955,13 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GrPrintf("AA RT requested but not supported on this platform.");
}
glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
glTexDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
// in case we need a temporary, trimmed copy of the src pixels
SkAutoSMalloc<128 * 128> tempStorage;
if (!rowBytes) {
rowBytes = glDesc.fUploadByteCount * desc.fWidth;
rowBytes = glTexDesc.fUploadByteCount * desc.fWidth;
}
/*
* check whether to allocate a temporary buffer for flipping y or
@ -961,14 +969,14 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
* to trim those off here, since GL ES doesn't let us specify
* GL_UNPACK_ROW_LENGTH.
*/
bool flipY = GrGLTexture::kBottomUp_Orientation == glDesc.fOrientation;
bool flipY = GrGLTexture::kBottomUp_Orientation == glTexDesc.fOrientation;
if (GR_GL_SUPPORT_DESKTOP && !flipY) {
if (srcData && rowBytes != desc.fWidth * glDesc.fUploadByteCount) {
if (srcData && rowBytes != desc.fWidth * glTexDesc.fUploadByteCount) {
GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
rowBytes / glDesc.fUploadByteCount));
rowBytes / glTexDesc.fUploadByteCount));
}
} else {
size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
size_t trimRowBytes = desc.fWidth * glTexDesc.fUploadByteCount;
if (srcData && (trimRowBytes < rowBytes || flipY)) {
// copy the data into our new storage, skipping the trailing bytes
size_t trimSize = desc.fHeight * trimRowBytes;
@ -994,33 +1002,33 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
if (renderTarget) {
if (!this->npotRenderTargetSupport()) {
glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
}
glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
glDesc.fAllocWidth);
glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
glDesc.fAllocHeight);
if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
glDesc.fAllocHeight > fMaxRenderTargetSize) {
glTexDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
glTexDesc.fAllocWidth);
glTexDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
glTexDesc.fAllocHeight);
if (glTexDesc.fAllocWidth > fMaxRenderTargetSize ||
glTexDesc.fAllocHeight > fMaxRenderTargetSize) {
return return_null_texture();
}
} else if (!this->npotTextureSupport()) {
glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
if (glDesc.fAllocWidth > fMaxTextureSize ||
glDesc.fAllocHeight > fMaxTextureSize) {
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glTexDesc.fAllocHeight = GrNextPow2(desc.fHeight);
if (glTexDesc.fAllocWidth > fMaxTextureSize ||
glTexDesc.fAllocHeight > fMaxTextureSize) {
return return_null_texture();
}
}
GR_GL(GenTextures(1, &glDesc.fTextureID));
if (!glDesc.fTextureID) {
GR_GL(GenTextures(1, &glTexDesc.fTextureID));
if (!glTexDesc.fTextureID) {
return return_null_texture();
}
GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
GR_GL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_MAG_FILTER,
DEFAULT_PARAMS.fFilter));
@ -1034,41 +1042,41 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GR_GL_TEXTURE_WRAP_T,
DEFAULT_PARAMS.fWrapT));
GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glTexDesc.fUploadByteCount));
if (kIndex_8_GrPixelConfig == desc.fFormat &&
supports8BitPalette()) {
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
GrAssert(desc.fWidth == glDesc.fAllocWidth);
GrAssert(desc.fHeight == glDesc.fAllocHeight);
GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
GrAssert(desc.fWidth == glTexDesc.fAllocWidth);
GrAssert(desc.fHeight == glTexDesc.fAllocHeight);
GrGLsizei imageSize = glTexDesc.fAllocWidth * glTexDesc.fAllocHeight +
kGrColorTableSize;
GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
glDesc.fAllocWidth, glDesc.fAllocHeight,
GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glTexDesc.fUploadFormat,
glTexDesc.fAllocWidth, glTexDesc.fAllocHeight,
0, imageSize, srcData));
GrGLRestoreResetRowLength();
} else {
if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
glDesc.fAllocHeight != desc.fHeight)) {
if (NULL != srcData && (glTexDesc.fAllocWidth != desc.fWidth ||
glTexDesc.fAllocHeight != desc.fHeight)) {
GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
glDesc.fAllocWidth, glDesc.fAllocHeight,
0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
glTexDesc.fAllocWidth, glTexDesc.fAllocHeight,
0, glTexDesc.fUploadFormat, glTexDesc.fUploadType, NULL));
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
desc.fHeight, glDesc.fUploadFormat,
glDesc.fUploadType, srcData));
desc.fHeight, glTexDesc.fUploadFormat,
glTexDesc.fUploadType, srcData));
GrGLRestoreResetRowLength();
int extraW = glDesc.fAllocWidth - desc.fWidth;
int extraH = glDesc.fAllocHeight - desc.fHeight;
int extraW = glTexDesc.fAllocWidth - desc.fWidth;
int extraH = glTexDesc.fAllocHeight - desc.fHeight;
int maxTexels = extraW * extraH;
maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
SkAutoSMalloc<128*128> texels(glTexDesc.fUploadByteCount * maxTexels);
// rowBytes is actual stride between rows in srcData
// rowDataBytes is the actual amount of non-pad data in a row
// and the stride used for uploading extraH rows.
uint32_t rowDataBytes = desc.fWidth * glDesc.fUploadByteCount;
uint32_t rowDataBytes = desc.fWidth * glTexDesc.fUploadByteCount;
if (extraH) {
uint8_t* lastRowStart = (uint8_t*) srcData +
(desc.fHeight - 1) * rowBytes;
@ -1079,51 +1087,54 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
extraRowStart += rowDataBytes;
}
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
extraH, glDesc.fUploadFormat, glDesc.fUploadType,
extraH, glTexDesc.fUploadFormat, glTexDesc.fUploadType,
texels.get()));
}
if (extraW) {
uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glDesc.fUploadByteCount;
uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glTexDesc.fUploadByteCount;
uint8_t* extraTexel = (uint8_t*)texels.get();
for (int j = 0; j < desc.fHeight; ++j) {
for (int i = 0; i < extraW; ++i) {
memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
extraTexel += glDesc.fUploadByteCount;
memcpy(extraTexel, edgeTexel, glTexDesc.fUploadByteCount);
extraTexel += glTexDesc.fUploadByteCount;
}
edgeTexel += rowBytes;
}
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
desc.fHeight, glDesc.fUploadFormat,
glDesc.fUploadType, texels.get()));
desc.fHeight, glTexDesc.fUploadFormat,
glTexDesc.fUploadType, texels.get()));
}
if (extraW && extraH) {
uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowBytes
- glDesc.fUploadByteCount;
- glTexDesc.fUploadByteCount;
uint8_t* extraTexel = (uint8_t*)texels.get();
for (int i = 0; i < extraW*extraH; ++i) {
memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
extraTexel += glDesc.fUploadByteCount;
memcpy(extraTexel, cornerTexel, glTexDesc.fUploadByteCount);
extraTexel += glTexDesc.fUploadByteCount;
}
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
extraW, extraH, glDesc.fUploadFormat,
glDesc.fUploadType, texels.get()));
extraW, extraH, glTexDesc.fUploadFormat,
glTexDesc.fUploadType, texels.get()));
}
} else {
GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
glDesc.fUploadType, srcData));
GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight, 0, glTexDesc.fUploadFormat,
glTexDesc.fUploadType, srcData));
GrGLRestoreResetRowLength();
}
}
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
rtIDs.fStencilRenderbufferID = 0;
rtIDs.fMSColorRenderbufferID = 0;
rtIDs.fRTFBOID = 0;
rtIDs.fTexFBOID = 0;
rtIDs.fOwnIDs = true;
GrGLRenderTarget::Desc glRTDesc;
glRTDesc.fStencilRenderbufferID = 0;
glRTDesc.fMSColorRenderbufferID = 0;
glRTDesc.fRTFBOID = 0;
glRTDesc.fTexFBOID = 0;
glRTDesc.fOwnIDs = true;
glRTDesc.fConfig = glTexDesc.fFormat;
glRTDesc.fSampleCnt = samples;
GrGLenum msColorRenderbufferFormat = -1;
if (renderTarget) {
@ -1134,29 +1145,29 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GrGLenum status;
GrGLint err;
GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
GrAssert(rtIDs.fTexFBOID);
GR_GL(GenFramebuffers(1, &glRTDesc.fTexFBOID));
GrAssert(glRTDesc.fTexFBOID);
// If we are using multisampling and we will create two FBOS We render
// to one and then resolve to the texture bound to the other.
if (samples > 1 && kNone_MSFBO != fMSFBOType) {
GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
GrAssert(0 != rtIDs.fRTFBOID);
GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
GrAssert(0 != rtIDs.fMSColorRenderbufferID);
GR_GL(GenFramebuffers(1, &glRTDesc.fRTFBOID));
GrAssert(0 != glRTDesc.fRTFBOID);
GR_GL(GenRenderbuffers(1, &glRTDesc.fMSColorRenderbufferID));
GrAssert(0 != glRTDesc.fMSColorRenderbufferID);
if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
GR_GL(DeleteTextures(1, &glDesc.fTextureID));
GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
GR_GL(DeleteRenderbuffers(1, &glRTDesc.fMSColorRenderbufferID));
GR_GL(DeleteTextures(1, &glTexDesc.fTextureID));
GR_GL(DeleteFramebuffers(1, &glRTDesc.fTexFBOID));
GR_GL(DeleteFramebuffers(1, &glRTDesc.fRTFBOID));
return return_null_texture();
}
} else {
rtIDs.fRTFBOID = rtIDs.fTexFBOID;
glRTDesc.fRTFBOID = glRTDesc.fTexFBOID;
}
if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
GrAssert(0 != rtIDs.fStencilRenderbufferID);
GR_GL(GenRenderbuffers(1, &glRTDesc.fStencilRenderbufferID));
GrAssert(0 != glRTDesc.fStencilRenderbufferID);
}
// someone suggested that some systems might require
@ -1167,7 +1178,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
err = ~GR_GL_NO_ERROR;
int stencilFmtCnt;
if (rtIDs.fStencilRenderbufferID) {
if (glRTDesc.fStencilRenderbufferID) {
stencilFmtCnt = fStencilFormats.count();
} else {
stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
@ -1179,43 +1190,43 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
// first (painful) stencil creation.
int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
if (rtIDs.fStencilRenderbufferID) {
if (glRTDesc.fStencilRenderbufferID) {
GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
rtIDs.fStencilRenderbufferID));
glRTDesc.fStencilRenderbufferID));
if (samples > 1) {
GR_GL_NO_ERR(RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
samples,
fStencilFormats[sIdx].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight));
} else {
GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
fStencilFormats[sIdx].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight));
}
err = GrGLGetGLInterface()->fGetError();
if (err != GR_GL_NO_ERROR) {
continue;
}
}
if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
if (glRTDesc.fRTFBOID != glRTDesc.fTexFBOID) {
GrAssert(samples > 1);
GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
rtIDs.fMSColorRenderbufferID));
glRTDesc.fMSColorRenderbufferID));
GR_GL_NO_ERR(RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
samples,
msColorRenderbufferFormat,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight));
err = GrGLGetGLInterface()->fGetError();
if (err != GR_GL_NO_ERROR) {
continue;
}
}
GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRTDesc.fTexFBOID));
#if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt;
@ -1223,42 +1234,42 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
glDesc.fTextureID, 0));
if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
glTexDesc.fTextureID, 0));
if (glRTDesc.fRTFBOID != glRTDesc.fTexFBOID) {
GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
continue;
}
GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRTDesc.fRTFBOID));
#if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt;
#endif
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_RENDERBUFFER,
rtIDs.fMSColorRenderbufferID));
glRTDesc.fMSColorRenderbufferID));
}
if (rtIDs.fStencilRenderbufferID) {
if (glRTDesc.fStencilRenderbufferID) {
// bind the stencil to rt fbo if present, othewise the tex fbo
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT,
GR_GL_RENDERBUFFER,
rtIDs.fStencilRenderbufferID));
glRTDesc.fStencilRenderbufferID));
// if it is a packed format bind to depth also, otherwise
// we may get an unsupported fbo completeness result
if (fStencilFormats[sIdx].fPacked) {
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER,
rtIDs.fStencilRenderbufferID));
glRTDesc.fStencilRenderbufferID));
}
}
status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
// undo the depth bind
if (rtIDs.fStencilRenderbufferID &&
if (glRTDesc.fStencilRenderbufferID &&
fStencilFormats[sIdx].fPacked) {
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
@ -1269,30 +1280,30 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
}
// we're successful!
failed = false;
if (rtIDs.fStencilRenderbufferID) {
if (glRTDesc.fStencilRenderbufferID) {
fLastSuccessfulStencilFmtIdx = sIdx;
if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glRTDesc.fStencilBits);
} else {
glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
glRTDesc.fStencilBits = fStencilFormats[sIdx].fBits;
}
}
break;
}
if (failed) {
if (rtIDs.fStencilRenderbufferID) {
GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
if (glRTDesc.fStencilRenderbufferID) {
GR_GL(DeleteRenderbuffers(1, &glRTDesc.fStencilRenderbufferID));
}
if (rtIDs.fMSColorRenderbufferID) {
GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
if (glRTDesc.fMSColorRenderbufferID) {
GR_GL(DeleteRenderbuffers(1, &glRTDesc.fMSColorRenderbufferID));
}
if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
if (glRTDesc.fRTFBOID != glRTDesc.fTexFBOID) {
GR_GL(DeleteFramebuffers(1, &glRTDesc.fRTFBOID));
}
if (rtIDs.fTexFBOID) {
GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
if (glRTDesc.fTexFBOID) {
GR_GL(DeleteFramebuffers(1, &glRTDesc.fTexFBOID));
}
GR_GL(DeleteTextures(1, &glDesc.fTextureID));
GR_GL(DeleteTextures(1, &glTexDesc.fTextureID));
return return_null_texture();
}
}
@ -1300,9 +1311,9 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
tex->fTextureID, width, height, tex->fUploadByteCount);
#endif
GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
if (0 != rtIDs.fTexFBOID) {
if (renderTarget) {
GrGLTexture* tex = new GrGLTexture(this, glTexDesc,
glRTDesc, DEFAULT_PARAMS);
GrRenderTarget* rt = tex->asRenderTarget();
// We've messed with FBO state but may not have set the correct viewport
// so just dirty the rendertarget state to force a resend.
@ -1315,8 +1326,10 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
this->clearStencil(0, ~0);
fCurrDrawState.fRenderTarget = rtSave;
}
return tex;
} else {
return new GrGLTexture(this, glTexDesc, DEFAULT_PARAMS);
}
return tex;
}
GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {

View File

@ -199,6 +199,7 @@
],
'defines': [
'GR_IMPLEMENTATION=1',
'GR_USE_PLATFORM_CREATE_SAMPLE_COUNT=1',
],
'conditions': [
[ 'skia_os == "linux"', {

View File

@ -132,7 +132,8 @@ public:
desc.fWidth = SkScalarRound(win->width());
desc.fHeight = SkScalarRound(win->height());
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fStencilBits = 8;
GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, &desc.fStencilBits);
GR_GL_GetIntegerv(GR_GL_SAMPLES, &desc.fSampleCnt);
GrGLint buffer;
GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
desc.fPlatformRenderTarget = buffer;