Add support for GL_NV_fence.
Will be used for YUV420 readback on ANGLE ES 2 contexts in Chrome. Marks the functions as required as Chrome now adds inits these on GrGLInterface. Bug: 1040643 Change-Id: I5504d4c9209874991592c9f86aaf7987c316aa40 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/265602 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
a7e557f3e3
commit
8675bcbaf9
@ -26,12 +26,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
|||||||
const GrGLInterface* glInterface) : INHERITED(contextOptions) {
|
const GrGLInterface* glInterface) : INHERITED(contextOptions) {
|
||||||
fStandard = ctxInfo.standard();
|
fStandard = ctxInfo.standard();
|
||||||
|
|
||||||
fStencilFormats.reset();
|
|
||||||
fMSFBOType = kNone_MSFBOType;
|
|
||||||
fInvalidateFBType = kNone_InvalidateFBType;
|
|
||||||
fMapBufferType = kNone_MapBufferType;
|
|
||||||
fTransferBufferType = TransferBufferType::kNone;
|
|
||||||
fMaxFragmentUniformVectors = 0;
|
|
||||||
fPackFlipYSupport = false;
|
fPackFlipYSupport = false;
|
||||||
fTextureUsageSupport = false;
|
fTextureUsageSupport = false;
|
||||||
fImagingSupport = false;
|
fImagingSupport = false;
|
||||||
@ -70,9 +64,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
|||||||
fFBFetchRequiresEnablePerSample = false;
|
fFBFetchRequiresEnablePerSample = false;
|
||||||
fSRGBWriteControl = false;
|
fSRGBWriteControl = false;
|
||||||
|
|
||||||
fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
|
|
||||||
fMaxInstancesPerDrawWithoutCrashing = 0;
|
|
||||||
|
|
||||||
fShaderCaps.reset(new GrShaderCaps(contextOptions));
|
fShaderCaps.reset(new GrShaderCaps(contextOptions));
|
||||||
|
|
||||||
this->init(contextOptions, ctxInfo, glInterface);
|
this->init(contextOptions, ctxInfo, glInterface);
|
||||||
@ -647,22 +638,29 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
|||||||
fDrawRangeElementsSupport = version >= GR_GL_VER(2,0);
|
fDrawRangeElementsSupport = version >= GR_GL_VER(2,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We prefer GL sync objects but also support NV_fence_sync. The former can be
|
||||||
|
// used to implements GrFence and GrSemaphore. The latter only implements GrFence.
|
||||||
// TODO: support CHROMIUM_sync_point and maybe KHR_fence_sync
|
// TODO: support CHROMIUM_sync_point and maybe KHR_fence_sync
|
||||||
if (ctxInfo.hasExtension("GL_ARB_sync") || ctxInfo.hasExtension("GL_APPLE_sync")) {
|
if (GR_IS_GR_WEBGL(standard)) {
|
||||||
fFenceSyncSupport = true;
|
|
||||||
} else if (GR_IS_GR_GL(standard)) {
|
|
||||||
fFenceSyncSupport = (version >= GR_GL_VER(3, 2));
|
|
||||||
} else if (GR_IS_GR_GL_ES(standard)) {
|
|
||||||
fFenceSyncSupport = (version >= GR_GL_VER(3, 0));
|
|
||||||
} else if (GR_IS_GR_WEBGL(standard)) {
|
|
||||||
// Only in WebGL 2.0
|
// Only in WebGL 2.0
|
||||||
fFenceSyncSupport = version >= GR_GL_VER(2, 0);
|
fSemaphoreSupport = fFenceSyncSupport = version >= GR_GL_VER(2, 0);
|
||||||
|
fFenceType = FenceType::kSyncObject;
|
||||||
|
} else if (ctxInfo.hasExtension("GL_ARB_sync") || ctxInfo.hasExtension("GL_APPLE_sync")) {
|
||||||
|
fSemaphoreSupport = fFenceSyncSupport = true;
|
||||||
|
fFenceType = FenceType::kSyncObject;
|
||||||
|
} else if (GR_IS_GR_GL(standard) && version >= GR_GL_VER(3, 2)) {
|
||||||
|
fSemaphoreSupport = fFenceSyncSupport = true;
|
||||||
|
fFenceType = FenceType::kSyncObject;
|
||||||
|
} else if (GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0)) {
|
||||||
|
fSemaphoreSupport = fFenceSyncSupport = true;
|
||||||
|
fFenceType = FenceType::kSyncObject;
|
||||||
|
} else if (ctxInfo.hasExtension("GL_NV_fence")) {
|
||||||
|
// This extension can exist in GL and GL ES. We have it last because we prefer the
|
||||||
|
// standard GLsync object implementation which also supports GPU semaphore semantics.
|
||||||
|
fFenceSyncSupport = true;
|
||||||
|
fFenceType = FenceType::kNVFence;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The same objects (GL sync objects) are used to implement GPU/CPU fence syncs and GPU/GPU
|
|
||||||
// semaphores.
|
|
||||||
fSemaphoreSupport = fFenceSyncSupport;
|
|
||||||
|
|
||||||
// Safely moving textures between contexts requires semaphores.
|
// Safely moving textures between contexts requires semaphores.
|
||||||
fCrossContextTextureSupport = fSemaphoreSupport;
|
fCrossContextTextureSupport = fSemaphoreSupport;
|
||||||
|
|
||||||
|
@ -100,6 +100,12 @@ public:
|
|||||||
kChromium, // CHROMIUM_pixel_transfer_buffer_object
|
kChromium, // CHROMIUM_pixel_transfer_buffer_object
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FenceType {
|
||||||
|
kNone,
|
||||||
|
kSyncObject,
|
||||||
|
kNVFence
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the GrGLCaps to the set of features supported in the current
|
* Initializes the GrGLCaps to the set of features supported in the current
|
||||||
* OpenGL context accessible via ctxInfo.
|
* OpenGL context accessible via ctxInfo.
|
||||||
@ -267,6 +273,9 @@ public:
|
|||||||
/// What type of transfer buffer is supported?
|
/// What type of transfer buffer is supported?
|
||||||
TransferBufferType transferBufferType() const { return fTransferBufferType; }
|
TransferBufferType transferBufferType() const { return fTransferBufferType; }
|
||||||
|
|
||||||
|
/// How are GrFences implemented?
|
||||||
|
FenceType fenceType() const { return fFenceType; }
|
||||||
|
|
||||||
/// The maximum number of fragment uniform vectors (GLES has min. 16).
|
/// The maximum number of fragment uniform vectors (GLES has min. 16).
|
||||||
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
|
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
|
||||||
|
|
||||||
@ -480,16 +489,17 @@ private:
|
|||||||
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
|
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
|
||||||
GrColorType) const override;
|
GrColorType) const override;
|
||||||
|
|
||||||
GrGLStandard fStandard;
|
GrGLStandard fStandard = kNone_GrGLStandard;
|
||||||
|
|
||||||
SkTArray<StencilFormat, true> fStencilFormats;
|
SkTArray<StencilFormat, true> fStencilFormats;
|
||||||
|
|
||||||
int fMaxFragmentUniformVectors;
|
int fMaxFragmentUniformVectors = 0;
|
||||||
|
|
||||||
MSFBOType fMSFBOType;
|
MSFBOType fMSFBOType = kNone_MSFBOType;
|
||||||
InvalidateFBType fInvalidateFBType;
|
InvalidateFBType fInvalidateFBType = kNone_InvalidateFBType;
|
||||||
MapBufferType fMapBufferType;
|
MapBufferType fMapBufferType = kNone_MapBufferType;
|
||||||
TransferBufferType fTransferBufferType;
|
TransferBufferType fTransferBufferType = TransferBufferType::kNone;
|
||||||
|
FenceType fFenceType = FenceType::kNone;
|
||||||
|
|
||||||
bool fPackFlipYSupport : 1;
|
bool fPackFlipYSupport : 1;
|
||||||
bool fTextureUsageSupport : 1;
|
bool fTextureUsageSupport : 1;
|
||||||
@ -530,9 +540,9 @@ private:
|
|||||||
bool fDetachStencilFromMSAABuffersBeforeReadPixels : 1;
|
bool fDetachStencilFromMSAABuffersBeforeReadPixels : 1;
|
||||||
bool fDontSetBaseOrMaxLevelForExternalTextures : 1;
|
bool fDontSetBaseOrMaxLevelForExternalTextures : 1;
|
||||||
bool fNeverDisableColorWrites : 1;
|
bool fNeverDisableColorWrites : 1;
|
||||||
int fMaxInstancesPerDrawWithoutCrashing;
|
int fMaxInstancesPerDrawWithoutCrashing = 0;
|
||||||
|
|
||||||
uint32_t fBlitFramebufferFlags;
|
uint32_t fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
|
||||||
|
|
||||||
struct ReadPixelsFormat {
|
struct ReadPixelsFormat {
|
||||||
ReadPixelsFormat() : fFormat(0), fType(0) {}
|
ReadPixelsFormat() : fFormat(0), fType(0) {}
|
||||||
|
@ -4076,16 +4076,41 @@ void GrGLGpu::submit(GrOpsRenderPass* renderPass) {
|
|||||||
GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
|
GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
|
||||||
SkASSERT(this->caps()->fenceSyncSupport());
|
SkASSERT(this->caps()->fenceSyncSupport());
|
||||||
GrGLsync sync;
|
GrGLsync sync;
|
||||||
GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
|
if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) {
|
||||||
|
static_assert(sizeof(GrGLsync) >= sizeof(GrGLuint));
|
||||||
|
GrGLuint fence = 0;
|
||||||
|
GL_CALL(GenFences(1, &fence));
|
||||||
|
GL_CALL(SetFence(fence, GR_GL_ALL_COMPLETED));
|
||||||
|
sync = reinterpret_cast<GrGLsync>(static_cast<intptr_t>(fence));
|
||||||
|
} else {
|
||||||
|
GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
|
||||||
|
}
|
||||||
static_assert(sizeof(GrFence) >= sizeof(GrGLsync));
|
static_assert(sizeof(GrFence) >= sizeof(GrGLsync));
|
||||||
return (GrFence)sync;
|
return (GrFence)sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrGLGpu::waitSync(GrGLsync sync, uint64_t timeout, bool flush) {
|
bool GrGLGpu::waitSync(GrGLsync sync, uint64_t timeout, bool flush) {
|
||||||
GrGLbitfield flags = flush ? GR_GL_SYNC_FLUSH_COMMANDS_BIT : 0;
|
if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) {
|
||||||
GrGLenum result;
|
GrGLuint nvFence = static_cast<GrGLuint>(reinterpret_cast<intptr_t>(sync));
|
||||||
GL_CALL_RET(result, ClientWaitSync(sync, flags, timeout));
|
if (!timeout) {
|
||||||
return (GR_GL_CONDITION_SATISFIED == result || GR_GL_ALREADY_SIGNALED == result);
|
if (flush) {
|
||||||
|
GL_CALL(Flush);
|
||||||
|
}
|
||||||
|
GrGLboolean result;
|
||||||
|
GL_CALL_RET(result, TestFence(nvFence));
|
||||||
|
return result == GR_GL_TRUE;
|
||||||
|
}
|
||||||
|
// Ignore non-zero timeouts. GL_NV_fence has no timeout functionality.
|
||||||
|
// If this really becomes necessary we could poll TestFence().
|
||||||
|
// FinishFence always flushes so no need to check flush param.
|
||||||
|
GL_CALL(FinishFence(nvFence));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
GrGLbitfield flags = flush ? GR_GL_SYNC_FLUSH_COMMANDS_BIT : 0;
|
||||||
|
GrGLenum result;
|
||||||
|
GL_CALL_RET(result, ClientWaitSync(sync, flags, timeout));
|
||||||
|
return (GR_GL_CONDITION_SATISFIED == result || GR_GL_ALREADY_SIGNALED == result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) {
|
bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) {
|
||||||
@ -4134,7 +4159,12 @@ void GrGLGpu::checkFinishProcs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrGLGpu::deleteSync(GrGLsync sync) const {
|
void GrGLGpu::deleteSync(GrGLsync sync) const {
|
||||||
GL_CALL(DeleteSync(sync));
|
if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) {
|
||||||
|
GrGLuint nvFence = SkToUInt(reinterpret_cast<intptr_t>(sync));
|
||||||
|
GL_CALL(DeleteFences(1, &nvFence));
|
||||||
|
} else {
|
||||||
|
GL_CALL(DeleteSync(sync));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrSemaphore> GrGLGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
|
std::unique_ptr<GrSemaphore> GrGLGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
|
||||||
|
@ -747,7 +747,13 @@ bool GrGLInterface::validate() const {
|
|||||||
fExtensions.has("GL_NV_fence"))) ||
|
fExtensions.has("GL_NV_fence"))) ||
|
||||||
(GR_IS_GR_GL_ES(fStandard) && (
|
(GR_IS_GR_GL_ES(fStandard) && (
|
||||||
fExtensions.has("GL_NV_fence")))) {
|
fExtensions.has("GL_NV_fence")))) {
|
||||||
// all functions were marked optional or test_only
|
if (!fFunctions.fDeleteFences ||
|
||||||
|
!fFunctions.fFinishFence ||
|
||||||
|
!fFunctions.fGenFences ||
|
||||||
|
!fFunctions.fSetFence ||
|
||||||
|
!fFunctions.fTestFence) {
|
||||||
|
RETURN_FALSE_INTERFACE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -731,8 +731,5 @@
|
|||||||
"functions": [
|
"functions": [
|
||||||
"DeleteFences", "FinishFence", "GenFences", "SetFence", "TestFence",
|
"DeleteFences", "FinishFence", "GenFences", "SetFence", "TestFence",
|
||||||
],
|
],
|
||||||
"optional": [
|
|
||||||
"DeleteFences", "FinishFence", "GenFences", "SetFence", "TestFence"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user