Add flag bits for partial GrContext reset

BUG=248728
R=bsalomon@google.com

Review URL: https://codereview.chromium.org/17027003

git-svn-id: http://skia.googlecode.com/svn/trunk@9802 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2013-06-28 14:32:08 +00:00
parent 6bf19415c3
commit cad107bbe7
6 changed files with 116 additions and 68 deletions

View File

@ -61,8 +61,10 @@ public:
* within the underlying 3D API's context/device/whatever. This call informs
* the context that the state was modified and it should resend. Shouldn't
* be called frequently for good performance.
* The flag bits, state, is dpendent on which backend is used by the
* context, either GL or D3D (possible in future).
*/
void resetContext();
void resetContext(uint32_t state = kALL_GrGLBackendState);
/**
* Callback function to allow classes to cleanup on GrContext destruction.

View File

@ -600,6 +600,25 @@ struct GrBackendRenderTargetDesc {
GrBackendObject fRenderTargetHandle;
};
/**
* The GrContext's cache of backend context state can be partially invalidated.
* These enums are specific to the GL backend and we'd add a new set for an alternative backend.
*/
enum GrGLBackendState {
kRenderTarget_GrGLBackendState = 1 << 0,
kTextureBinding_GrGLBackendState = 1 << 1,
// View state stands for scissor and viewport
kView_GrGLBackendState = 1 << 2,
kBlend_GrGLBackendState = 1 << 3,
kAA_GrGLBackendState = 1 << 4,
kVertex_GrGLBackendState = 1 << 5,
kStencil_GrGLBackendState = 1 << 6,
kPixelStore_GrGLBackendState = 1 << 7,
kProgram_GrGLBackendState = 1 << 8,
kPathStencil_GrGLBackendState = 1 << 9,
kMisc_GrGLBackendState = 1 << 10,
kALL_GrGLBackendState = 0xffff
};
///////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -204,8 +204,8 @@ void GrContext::contextDestroyed() {
fGpu->markContextDirty();
}
void GrContext::resetContext() {
fGpu->markContextDirty();
void GrContext::resetContext(uint32_t state) {
fGpu->markContextDirty(state);
}
void GrContext::freeGpuResources() {

View File

@ -66,7 +66,10 @@ public:
* the GrGpu that the state was modified and it shouldn't make assumptions
* about the state.
*/
void markContextDirty() { fContextIsDirty = true; }
void markContextDirty(uint32_t state = kALL_GrGLBackendState) {
fContextIsDirty = true;
fResetBits |= state;
}
void unimpl(const char[]);
@ -426,7 +429,7 @@ private:
// called when the 3D context state is unknown. Subclass should emit any
// assumed 3D context state and dirty any state cache.
virtual void onResetContext() = 0;
virtual void onResetContext(uint32_t resetBits) = 0;
// overridden by backend-specific derived class to create objects.
virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
@ -507,7 +510,8 @@ private:
// stencil buffer. Perhaps we should detect whether it is a
// internally created stencil buffer and if so skip the invalidate.
fClipMaskManager.invalidateStencilMask();
this->onResetContext();
this->onResetContext(fResetBits);
fResetBits = 0;
++fResetTimestamp;
}
@ -532,6 +536,7 @@ private:
// these are mutable so they can be created on-demand
mutable GrIndexBuffer* fQuadIndexBuffer;
bool fContextIsDirty;
uint32_t fResetBits;
// Used to abandon/release all resources created by this GrGpu. TODO: Move this
// functionality to GrResourceCache.
ResourceList fResourceList;

View File

@ -282,88 +282,110 @@ bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const {
return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL);
}
void GrGpuGL::onResetContext() {
void GrGpuGL::onResetContext(uint32_t resetBits) {
// we don't use the zb at all
GL_CALL(Disable(GR_GL_DEPTH_TEST));
GL_CALL(DepthMask(GR_GL_FALSE));
if (resetBits & kMisc_GrGLBackendState) {
GL_CALL(Disable(GR_GL_DEPTH_TEST));
GL_CALL(DepthMask(GR_GL_FALSE));
fHWDrawFace = GrDrawState::kInvalid_DrawFace;
fHWDitherEnabled = kUnknown_TriState;
fHWDrawFace = GrDrawState::kInvalid_DrawFace;
fHWDitherEnabled = kUnknown_TriState;
if (kDesktop_GrGLBinding == this->glBinding()) {
// Desktop-only state that we never change
if (!this->glCaps().isCoreProfile()) {
GL_CALL(Disable(GR_GL_POINT_SMOOTH));
GL_CALL(Disable(GR_GL_LINE_SMOOTH));
GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
if (kDesktop_GrGLBinding == this->glBinding()) {
// Desktop-only state that we never change
if (!this->glCaps().isCoreProfile()) {
GL_CALL(Disable(GR_GL_POINT_SMOOTH));
GL_CALL(Disable(GR_GL_LINE_SMOOTH));
GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
}
// The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a
// core profile. This seems like a bug since the core spec removes any mention of
// GL_ARB_imaging.
if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
GL_CALL(Disable(GR_GL_COLOR_TABLE));
}
GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
// Since ES doesn't support glPointSize at all we always use the VS to
// set the point size
GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
// We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
// currently part of our gl interface. There are probably others as
// well.
}
// The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a core
// profile. This seems like a bug since the core spec removes any mention of GL_ARB_imaging.
if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
GL_CALL(Disable(GR_GL_COLOR_TABLE));
}
GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
// Since ES doesn't support glPointSize at all we always use the VS to
// set the point size
GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
// We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
// currently part of our gl interface. There are probably others as
// well.
fHWWriteToColor = kUnknown_TriState;
// we only ever use lines in hairline mode
GL_CALL(LineWidth(1));
}
fHWAAState.invalidate();
fHWWriteToColor = kUnknown_TriState;
// we only ever use lines in hairline mode
GL_CALL(LineWidth(1));
if (resetBits & kAA_GrGLBackendState) {
fHWAAState.invalidate();
}
// invalid
fHWActiveTextureUnitIdx = -1;
fHWBlendState.invalidate();
for (int s = 0; s < fHWBoundTextures.count(); ++s) {
fHWBoundTextures[s] = NULL;
if (resetBits & kTextureBinding_GrGLBackendState) {
fHWActiveTextureUnitIdx = -1;
for (int s = 0; s < fHWBoundTextures.count(); ++s) {
fHWBoundTextures[s] = NULL;
}
}
fHWScissorSettings.invalidate();
if (resetBits & kBlend_GrGLBackendState) {
fHWBlendState.invalidate();
}
fHWViewport.invalidate();
if (resetBits & kView_GrGLBackendState) {
fHWScissorSettings.invalidate();
fHWViewport.invalidate();
}
fHWStencilSettings.invalidate();
fHWStencilTestEnabled = kUnknown_TriState;
if (resetBits & kStencil_GrGLBackendState) {
fHWStencilSettings.invalidate();
fHWStencilTestEnabled = kUnknown_TriState;
}
fHWGeometryState.invalidate();
// Vertex
if (resetBits & kVertex_GrGLBackendState) {
fHWGeometryState.invalidate();
}
fHWBoundRenderTarget = NULL;
if (resetBits & kRenderTarget_GrGLBackendState) {
fHWBoundRenderTarget = NULL;
}
fHWPathStencilMatrixState.invalidate();
if (this->caps()->pathStencilingSupport()) {
// we don't use the model view matrix.
GL_CALL(MatrixMode(GR_GL_MODELVIEW));
GL_CALL(LoadIdentity());
if (resetBits & kPathStencil_GrGLBackendState) {
fHWPathStencilMatrixState.invalidate();
if (this->caps()->pathStencilingSupport()) {
// we don't use the model view matrix.
GL_CALL(MatrixMode(GR_GL_MODELVIEW));
GL_CALL(LoadIdentity());
}
}
// we assume these values
if (this->glCaps().unpackRowLengthSupport()) {
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
}
if (this->glCaps().packRowLengthSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
}
if (this->glCaps().unpackFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
}
if (this->glCaps().packFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
if (resetBits & kPixelStore_GrGLBackendState) {
if (this->glCaps().unpackRowLengthSupport()) {
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
}
if (this->glCaps().packRowLengthSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
}
if (this->glCaps().unpackFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
}
if (this->glCaps().packFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
}
}
fHWProgramID = 0;
fSharedGLProgramState.invalidate();
if (resetBits & kProgram_GrGLBackendState) {
fHWProgramID = 0;
fSharedGLProgramState.invalidate();
}
}
namespace {

View File

@ -102,7 +102,7 @@ protected:
private:
// GrGpu overrides
virtual void onResetContext() SK_OVERRIDE;
virtual void onResetContext(uint32_t resetBits) SK_OVERRIDE;
virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,