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) {
|
||||
fStandard = ctxInfo.standard();
|
||||
|
||||
fStencilFormats.reset();
|
||||
fMSFBOType = kNone_MSFBOType;
|
||||
fInvalidateFBType = kNone_InvalidateFBType;
|
||||
fMapBufferType = kNone_MapBufferType;
|
||||
fTransferBufferType = TransferBufferType::kNone;
|
||||
fMaxFragmentUniformVectors = 0;
|
||||
fPackFlipYSupport = false;
|
||||
fTextureUsageSupport = false;
|
||||
fImagingSupport = false;
|
||||
@ -70,9 +64,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
||||
fFBFetchRequiresEnablePerSample = false;
|
||||
fSRGBWriteControl = false;
|
||||
|
||||
fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
|
||||
fMaxInstancesPerDrawWithoutCrashing = 0;
|
||||
|
||||
fShaderCaps.reset(new GrShaderCaps(contextOptions));
|
||||
|
||||
this->init(contextOptions, ctxInfo, glInterface);
|
||||
@ -647,22 +638,29 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
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
|
||||
if (ctxInfo.hasExtension("GL_ARB_sync") || ctxInfo.hasExtension("GL_APPLE_sync")) {
|
||||
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)) {
|
||||
if (GR_IS_GR_WEBGL(standard)) {
|
||||
// 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.
|
||||
fCrossContextTextureSupport = fSemaphoreSupport;
|
||||
|
||||
|
@ -100,6 +100,12 @@ public:
|
||||
kChromium, // CHROMIUM_pixel_transfer_buffer_object
|
||||
};
|
||||
|
||||
enum class FenceType {
|
||||
kNone,
|
||||
kSyncObject,
|
||||
kNVFence
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the GrGLCaps to the set of features supported in the current
|
||||
* OpenGL context accessible via ctxInfo.
|
||||
@ -267,6 +273,9 @@ public:
|
||||
/// What type of transfer buffer is supported?
|
||||
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).
|
||||
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
|
||||
|
||||
@ -480,16 +489,17 @@ private:
|
||||
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
|
||||
GrColorType) const override;
|
||||
|
||||
GrGLStandard fStandard;
|
||||
GrGLStandard fStandard = kNone_GrGLStandard;
|
||||
|
||||
SkTArray<StencilFormat, true> fStencilFormats;
|
||||
|
||||
int fMaxFragmentUniformVectors;
|
||||
int fMaxFragmentUniformVectors = 0;
|
||||
|
||||
MSFBOType fMSFBOType;
|
||||
InvalidateFBType fInvalidateFBType;
|
||||
MapBufferType fMapBufferType;
|
||||
TransferBufferType fTransferBufferType;
|
||||
MSFBOType fMSFBOType = kNone_MSFBOType;
|
||||
InvalidateFBType fInvalidateFBType = kNone_InvalidateFBType;
|
||||
MapBufferType fMapBufferType = kNone_MapBufferType;
|
||||
TransferBufferType fTransferBufferType = TransferBufferType::kNone;
|
||||
FenceType fFenceType = FenceType::kNone;
|
||||
|
||||
bool fPackFlipYSupport : 1;
|
||||
bool fTextureUsageSupport : 1;
|
||||
@ -530,9 +540,9 @@ private:
|
||||
bool fDetachStencilFromMSAABuffersBeforeReadPixels : 1;
|
||||
bool fDontSetBaseOrMaxLevelForExternalTextures : 1;
|
||||
bool fNeverDisableColorWrites : 1;
|
||||
int fMaxInstancesPerDrawWithoutCrashing;
|
||||
int fMaxInstancesPerDrawWithoutCrashing = 0;
|
||||
|
||||
uint32_t fBlitFramebufferFlags;
|
||||
uint32_t fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
|
||||
|
||||
struct ReadPixelsFormat {
|
||||
ReadPixelsFormat() : fFormat(0), fType(0) {}
|
||||
|
@ -4076,16 +4076,41 @@ void GrGLGpu::submit(GrOpsRenderPass* renderPass) {
|
||||
GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() {
|
||||
SkASSERT(this->caps()->fenceSyncSupport());
|
||||
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));
|
||||
return (GrFence)sync;
|
||||
}
|
||||
|
||||
bool GrGLGpu::waitSync(GrGLsync sync, uint64_t timeout, bool flush) {
|
||||
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);
|
||||
if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) {
|
||||
GrGLuint nvFence = static_cast<GrGLuint>(reinterpret_cast<intptr_t>(sync));
|
||||
if (!timeout) {
|
||||
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) {
|
||||
@ -4134,7 +4159,12 @@ void GrGLGpu::checkFinishProcs() {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -747,7 +747,13 @@ bool GrGLInterface::validate() const {
|
||||
fExtensions.has("GL_NV_fence"))) ||
|
||||
(GR_IS_GR_GL_ES(fStandard) && (
|
||||
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": [
|
||||
"DeleteFences", "FinishFence", "GenFences", "SetFence", "TestFence",
|
||||
],
|
||||
"optional": [
|
||||
"DeleteFences", "FinishFence", "GenFences", "SetFence", "TestFence"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user