15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_fence.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GLFenceNVFence: public gfx::GLFence { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 15871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org GLFenceNVFence(bool flush) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // What if either of these GL calls fails? TestFenceNV will return true. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See spec: 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://www.opengl.org/registry/specs/NV/fence.txt 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // What should happen if TestFenceNV is called for a name before SetFenceNV 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is called? 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We generate an INVALID_OPERATION error, and return TRUE. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This follows the semantics for texture object names before 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they are bound, in that they acquire their state upon binding. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will arbitrarily return TRUE for consistency. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGenFencesNV(1, &fence_); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glSetFenceNV(fence_, GL_ALL_COMPLETED_NV); 28871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (flush) 29871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org glFlush(); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool HasCompleted() OVERRIDE { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return !!glTestFenceNV(fence_); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void ClientWait() OVERRIDE { 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch glFinishFenceNV(fence_); 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 40871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org virtual void ServerWait() OVERRIDE { 41871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org glFinishFenceNV(fence_); 42871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org } 43871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GLFenceNVFence() { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteFencesNV(1, &fence_); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint fence_; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GLFenceARBSync: public gfx::GLFence { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 54871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org GLFenceARBSync(bool flush) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 56871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (flush) 57871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org glFlush(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool HasCompleted() OVERRIDE { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle the case where FenceSync failed. 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!sync_) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // We could potentially use glGetSynciv here, but it doesn't work 66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // on OSX 10.7 (always says the fence is not signaled yet). 67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // glClientWaitSync works better, so let's use that instead. 68558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void ClientWait() OVERRIDE { 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 75871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org virtual void ServerWait() OVERRIDE { 76871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED); 77871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org } 78871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GLFenceARBSync() { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteSync(sync_); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLsync sync_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if !defined(OS_MACOSX) 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass EGLFenceSync : public gfx::GLFence { 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 90871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org EGLFenceSync(bool flush) { 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch display_ = eglGetCurrentDisplay(); 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); 93871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (flush) 94871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org glFlush(); 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual bool HasCompleted() OVERRIDE { 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EGLint value = 0; 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value); 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR); 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return !value || value == EGL_SIGNALED_KHR; 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void ClientWait() OVERRIDE { 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EGLint flags = 0; 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EGLTimeKHR time = EGL_FOREVER_KHR; 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eglClientWaitSyncKHR(display_, sync_, flags, time); 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 110871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org virtual void ServerWait() OVERRIDE { 111871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org EGLint flags = 0; 112871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org eglWaitSyncKHR(display_, sync_, flags); 113871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org } 114871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 115871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~EGLFenceSync() { 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch eglDestroySyncKHR(display_, sync_); 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EGLSyncKHR sync_; 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EGLDisplay display_; 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif // !OS_MACOSX 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 126871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org// static 127871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.orggfx::GLFence* CreateFence(bool flush) { 128871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org#if !defined(OS_MACOSX) 129871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) 130871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return new EGLFenceSync(flush); 131871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org#endif 132871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (gfx::g_driver_gl.ext.b_GL_NV_fence) 133871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return new GLFenceNVFence(flush); 134871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org if (gfx::g_driver_gl.ext.b_GL_ARB_sync) 135871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return new GLFenceARBSync(flush); 136871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return NULL; 137871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org} 138871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLFence::GLFence() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLFence::~GLFence() { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLFence* GLFence::Create() { 150871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return CreateFence(true); 151871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org} 152871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org 153871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.orgGLFence* GLFence::CreateWithoutFlush() { 154871ad5406650fa38062582bc125fffcd2f6d5159sievers@chromium.org return CreateFence(false); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 158