Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: ui/gl/gl_fence.cc

Issue 197563003: gpu: Allow fences to check whether a flush has occurred (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gl/gl_fence.h" 5 #include "ui/gl/gl_fence.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "ui/gl/gl_bindings.h" 8 #include "ui/gl/gl_bindings.h"
9 #include "ui/gl/gl_context.h" 9 #include "ui/gl/gl_context.h"
10 10
11 namespace { 11 namespace {
12 12
13 class GLFenceNVFence: public gfx::GLFence { 13 class GLFenceNVFence: public gfx::GLFence {
14 public: 14 public:
15 GLFenceNVFence(bool flush) { 15 GLFenceNVFence(bool flush) {
16 // What if either of these GL calls fails? TestFenceNV will return true. 16 // What if either of these GL calls fails? TestFenceNV will return true.
17 // See spec: 17 // See spec:
18 // http://www.opengl.org/registry/specs/NV/fence.txt 18 // http://www.opengl.org/registry/specs/NV/fence.txt
19 // 19 //
20 // What should happen if TestFenceNV is called for a name before SetFenceNV 20 // What should happen if TestFenceNV is called for a name before SetFenceNV
21 // is called? 21 // is called?
22 // We generate an INVALID_OPERATION error, and return TRUE. 22 // We generate an INVALID_OPERATION error, and return TRUE.
23 // This follows the semantics for texture object names before 23 // This follows the semantics for texture object names before
24 // they are bound, in that they acquire their state upon binding. 24 // they are bound, in that they acquire their state upon binding.
25 // We will arbitrarily return TRUE for consistency. 25 // We will arbitrarily return TRUE for consistency.
26 glGenFencesNV(1, &fence_); 26 glGenFencesNV(1, &fence_);
27 glSetFenceNV(fence_, GL_ALL_COMPLETED_NV); 27 glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
28 if (flush) 28 if (flush) {
29 glFlush(); 29 glFlush();
30 } else {
31 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
32 }
30 } 33 }
31 34
32 virtual bool HasCompleted() OVERRIDE { 35 virtual bool HasCompleted() OVERRIDE {
33 return !!glTestFenceNV(fence_); 36 return !!glTestFenceNV(fence_);
34 } 37 }
35 38
36 virtual void ClientWait() OVERRIDE { 39 virtual void ClientWait() OVERRIDE {
37 glFinishFenceNV(fence_); 40 if (flush_event_->IsSignaled()) {
piman 2014/03/15 00:18:40 (here an below), you also need to check for flush_
no sievers 2014/03/19 01:25:21 Done.
41 glFinishFenceNV(fence_);
42 } else {
43 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
44 NOTREACHED();
piman 2014/03/15 00:18:40 Maybe remove the NOTREACHED. It can be reached fro
no sievers 2014/03/19 01:25:21 Done.
45 }
38 } 46 }
39 47
40 virtual void ServerWait() OVERRIDE { 48 virtual void ServerWait() OVERRIDE {
41 glFinishFenceNV(fence_); 49 ClientWait();
42 } 50 }
43 51
44 private: 52 private:
45 virtual ~GLFenceNVFence() { 53 virtual ~GLFenceNVFence() {
46 glDeleteFencesNV(1, &fence_); 54 glDeleteFencesNV(1, &fence_);
47 } 55 }
48 56
49 GLuint fence_; 57 GLuint fence_;
58 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
50 }; 59 };
51 60
52 class GLFenceARBSync: public gfx::GLFence { 61 class GLFenceARBSync: public gfx::GLFence {
53 public: 62 public:
54 GLFenceARBSync(bool flush) { 63 GLFenceARBSync(bool flush) {
55 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 64 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
56 if (flush) 65 if (flush) {
57 glFlush(); 66 glFlush();
67 } else {
68 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
69 }
58 } 70 }
59 71
60 virtual bool HasCompleted() OVERRIDE { 72 virtual bool HasCompleted() OVERRIDE {
61 // Handle the case where FenceSync failed. 73 // Handle the case where FenceSync failed.
62 if (!sync_) 74 if (!sync_)
63 return true; 75 return true;
64 76
65 // We could potentially use glGetSynciv here, but it doesn't work 77 // We could potentially use glGetSynciv here, but it doesn't work
66 // on OSX 10.7 (always says the fence is not signaled yet). 78 // on OSX 10.7 (always says the fence is not signaled yet).
67 // glClientWaitSync works better, so let's use that instead. 79 // glClientWaitSync works better, so let's use that instead.
68 return glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED; 80 return glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED;
69 } 81 }
70 82
71 virtual void ClientWait() OVERRIDE { 83 virtual void ClientWait() OVERRIDE {
72 glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); 84 if (flush_event_->IsSignaled()) {
85 glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
86 } else {
87 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
88 NOTREACHED();
89 }
73 } 90 }
74 91
75 virtual void ServerWait() OVERRIDE { 92 virtual void ServerWait() OVERRIDE {
76 glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED); 93 if (flush_event_->IsSignaled()) {
94 glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
95 } else {
96 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
97 NOTREACHED();
98 }
77 } 99 }
78 100
79 private: 101 private:
80 virtual ~GLFenceARBSync() { 102 virtual ~GLFenceARBSync() {
81 glDeleteSync(sync_); 103 glDeleteSync(sync_);
82 } 104 }
83 105
84 GLsync sync_; 106 GLsync sync_;
107 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
85 }; 108 };
86 109
87 #if !defined(OS_MACOSX) 110 #if !defined(OS_MACOSX)
88 class EGLFenceSync : public gfx::GLFence { 111 class EGLFenceSync : public gfx::GLFence {
89 public: 112 public:
90 EGLFenceSync(bool flush) { 113 EGLFenceSync(bool flush) {
91 display_ = eglGetCurrentDisplay(); 114 display_ = eglGetCurrentDisplay();
92 sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); 115 sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
93 if (flush) 116 if (flush) {
94 glFlush(); 117 glFlush();
118 } else {
119 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
120 }
95 } 121 }
96 122
97 virtual bool HasCompleted() OVERRIDE { 123 virtual bool HasCompleted() OVERRIDE {
98 EGLint value = 0; 124 EGLint value = 0;
99 eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value); 125 eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value);
100 DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR); 126 DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
101 return !value || value == EGL_SIGNALED_KHR; 127 return !value || value == EGL_SIGNALED_KHR;
102 } 128 }
103 129
104 virtual void ClientWait() OVERRIDE { 130 virtual void ClientWait() OVERRIDE {
105 EGLint flags = 0; 131 if (flush_event_->IsSignaled()) {
106 EGLTimeKHR time = EGL_FOREVER_KHR; 132 EGLint flags = 0;
107 eglClientWaitSyncKHR(display_, sync_, flags, time); 133 EGLTimeKHR time = EGL_FOREVER_KHR;
134 eglClientWaitSyncKHR(display_, sync_, flags, time);
135 } else {
136 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
137 NOTREACHED();
138 }
108 } 139 }
109 140
110 virtual void ServerWait() OVERRIDE { 141 virtual void ServerWait() OVERRIDE {
111 EGLint flags = 0; 142 if (flush_event_->IsSignaled()) {
112 eglWaitSyncKHR(display_, sync_, flags); 143 EGLint flags = 0;
144 eglWaitSyncKHR(display_, sync_, flags);
145 } else {
146 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
147 NOTREACHED();
148 }
113 } 149 }
114 150
115 151
116 private: 152 private:
117 virtual ~EGLFenceSync() { 153 virtual ~EGLFenceSync() {
118 eglDestroySyncKHR(display_, sync_); 154 eglDestroySyncKHR(display_, sync_);
119 } 155 }
120 156
121 EGLSyncKHR sync_; 157 EGLSyncKHR sync_;
122 EGLDisplay display_; 158 EGLDisplay display_;
159 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
123 }; 160 };
124 #endif // !OS_MACOSX 161 #endif // !OS_MACOSX
125 162
126 // static 163 // static
127 gfx::GLFence* CreateFence(bool flush) { 164 gfx::GLFence* CreateFence(bool flush) {
165 if (!gfx::GLContext::GetCurrent()) {
piman 2014/03/15 00:18:40 nit: simply DCHECK(gfx::GLContext::GetCurrent()) ?
no sievers 2014/03/19 01:25:21 Done.
166 NOTREACHED() << "Trying to create fence with no context";
167 return NULL;
168 }
128 #if !defined(OS_MACOSX) 169 #if !defined(OS_MACOSX)
129 if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) 170 if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync)
130 return new EGLFenceSync(flush); 171 return new EGLFenceSync(flush);
131 #endif 172 #endif
132 if (gfx::g_driver_gl.ext.b_GL_NV_fence) 173 if (gfx::g_driver_gl.ext.b_GL_NV_fence)
133 return new GLFenceNVFence(flush); 174 return new GLFenceNVFence(flush);
134 if (gfx::g_driver_gl.ext.b_GL_ARB_sync) 175 if (gfx::g_driver_gl.ext.b_GL_ARB_sync)
135 return new GLFenceARBSync(flush); 176 return new GLFenceARBSync(flush);
136 return NULL; 177 return NULL;
137 } 178 }
(...skipping 10 matching lines...) Expand all
148 189
149 GLFence* GLFence::Create() { 190 GLFence* GLFence::Create() {
150 return CreateFence(true); 191 return CreateFence(true);
151 } 192 }
152 193
153 GLFence* GLFence::CreateWithoutFlush() { 194 GLFence* GLFence::CreateWithoutFlush() {
154 return CreateFence(false); 195 return CreateFence(false);
155 } 196 }
156 197
157 } // namespace gfx 198 } // namespace gfx
OLDNEW
« ui/gl/gl_context.cc ('K') | « ui/gl/gl_fence.h ('k') | ui/gl/gl_gl_api_implementation.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698