OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "gl/SkGLContext.h" | 8 #include "gl/SkGLContext.h" |
9 #include "GrGLUtil.h" | 9 #include "GrGLUtil.h" |
10 #include "SkGpuFenceSync.h" | |
11 | |
12 class SkGLContext::GLFenceSync : public SkGpuFenceSync { | |
13 public: | |
14 static GLFenceSync* CreateIfSupported(const SkGLContext*); | |
15 | |
16 SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; | |
17 bool flushAndWaitFence(SkPlatformGpuFence fence) const override; | |
18 void deleteFence(SkPlatformGpuFence fence) const override; | |
19 | |
20 private: | |
21 GLFenceSync() {} | |
22 | |
23 static const GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117; | |
24 static const GrGLenum GL_WAIT_FAILED = 0x911d; | |
25 static const GrGLbitfield GL_SYNC_FLUSH_COMMANDS_BIT = 0x00000001; | |
26 | |
27 typedef struct __GLsync *GLsync; | |
28 | |
29 typedef GLsync (GR_GL_FUNCTION_TYPE* GLFenceSyncProc) (GrGLenum, GrGLbitfiel d); | |
30 typedef GrGLenum (GR_GL_FUNCTION_TYPE* GLClientWaitSyncProc) (GLsync, GrGLbi tfield, GrGLuint64); | |
31 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GLDeleteSyncProc) (GLsync); | |
32 | |
33 GLFenceSyncProc fGLFenceSync; | |
34 GLClientWaitSyncProc fGLClientWaitSync; | |
35 GLDeleteSyncProc fGLDeleteSync; | |
36 | |
37 typedef SkGpuFenceSync INHERITED; | |
38 }; | |
10 | 39 |
11 SkGLContext::SkGLContext() { | 40 SkGLContext::SkGLContext() { |
41 memset(fFrameFences, 0, sizeof(fFrameFences)); | |
12 } | 42 } |
13 | 43 |
14 SkGLContext::~SkGLContext() { | 44 SkGLContext::~SkGLContext() { |
15 SkASSERT(NULL == fGL.get()); // Subclass should destroy the interface. | 45 // Subclass should call teardown. |
46 SkASSERT(0 == fFrameFences[0]); | |
bsalomon
2015/06/23 14:53:21
Can we write this class in a way that it will work
Chris Dalton
2015/06/23 19:34:11
Done.
| |
47 SkASSERT(0 == fFrameFences[1]); | |
48 SkASSERT(NULL == fGL.get()); | |
49 SkASSERT(NULL == fFenceSync.get()); | |
50 } | |
51 | |
52 void SkGLContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) { | |
53 SkASSERT(!fGL.get()); | |
54 fGL.reset(gl); | |
55 fFenceSync.reset(fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this )); | |
56 } | |
57 | |
58 void SkGLContext::teardown() { | |
59 if (fFenceSync) { | |
60 if (fFrameFences[0]) { | |
61 fFenceSync->deleteFence(fFrameFences[0]); | |
62 fFrameFences[0] = 0; | |
63 } | |
64 if (fFrameFences[1]) { | |
65 fFenceSync->deleteFence(fFrameFences[1]); | |
66 fFrameFences[1] = 0; | |
67 } | |
68 } | |
69 | |
70 fGL.reset(NULL); | |
71 fFenceSync.reset(NULL); | |
72 } | |
73 | |
74 void SkGLContext::makeCurrent() const { | |
75 this->onPlatformMakeCurrent(); | |
76 } | |
77 | |
78 void SkGLContext::swapBuffers() { | |
79 if (!fFenceSync) { | |
80 // Fallback on the platform SwapBuffers method for synchronization. This may have no effect. | |
81 this->onPlatformSwapBuffers(); | |
82 return; | |
83 } | |
84 | |
85 if (fFrameFences[1]) { | |
86 if (!fFenceSync->flushAndWaitFence(fFrameFences[1])) { | |
87 SkDebugf("WARNING: Wait failed for fence sync. Timings might not be accurate.\n"); | |
88 } | |
89 fFenceSync->deleteFence(fFrameFences[1]); | |
90 } | |
91 | |
92 fFrameFences[1] = fFrameFences[0]; | |
93 fFrameFences[0] = fFenceSync->insertFence(); | |
16 } | 94 } |
17 | 95 |
18 void SkGLContext::testAbandon() { | 96 void SkGLContext::testAbandon() { |
19 if (fGL) { | 97 if (fGL) { |
20 fGL->abandon(); | 98 fGL->abandon(); |
21 } | 99 } |
100 if (fFenceSync) { | |
101 memset(fFrameFences, 0, sizeof(fFrameFences)); | |
102 } | |
22 } | 103 } |
104 | |
105 SkGLContext::GLFenceSync* SkGLContext::GLFenceSync::CreateIfSupported(const SkGL Context* ctx) { | |
106 SkAutoTDelete<GLFenceSync> ret(SkNEW(GLFenceSync)); | |
107 | |
108 if (kGL_GrGLStandard == ctx->gl()->fStandard) { | |
109 const GrGLubyte* versionStr; | |
110 SK_GL_RET(*ctx, versionStr, GetString(GR_GL_VERSION)); | |
111 GrGLVersion version = GrGLGetVersionFromString(reinterpret_cast<const ch ar*>(versionStr)); | |
112 if (version < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync")) { | |
113 return NULL; | |
114 } | |
115 ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( | |
116 ctx->onPlatformGetProcAddress("glFenceSync")); | |
117 ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( | |
118 ctx->onPlatformGetProcAddress("glClientWaitSync")); | |
119 ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( | |
120 ctx->onPlatformGetProcAddress("glDeleteSync")); | |
121 } else { | |
122 if (!ctx->gl()->hasExtension("GL_APPLE_sync")) { | |
123 return NULL; | |
124 } | |
125 ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( | |
126 ctx->onPlatformGetProcAddress("glFenceSyncAPPLE")); | |
127 ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( | |
128 ctx->onPlatformGetProcAddress("glClientWaitSyncAPPLE")); | |
129 ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( | |
130 ctx->onPlatformGetProcAddress("glDeleteSyncAPPLE")); | |
131 } | |
132 | |
133 if (!ret->fGLFenceSync || !ret->fGLClientWaitSync || !ret->fGLDeleteSync) { | |
134 return NULL; | |
135 } | |
136 | |
137 return ret.detach(); | |
138 } | |
139 | |
140 SkPlatformGpuFence SkGLContext::GLFenceSync::insertFence() const { | |
141 return fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | |
142 } | |
143 | |
144 bool SkGLContext::GLFenceSync::flushAndWaitFence(SkPlatformGpuFence fence) const { | |
145 GLsync glsync = static_cast<GLsync>(fence); | |
146 return GL_WAIT_FAILED != fGLClientWaitSync(glsync, GL_SYNC_FLUSH_COMMANDS_BI T, -1); | |
147 } | |
148 | |
149 void SkGLContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const { | |
150 GLsync glsync = static_cast<GLsync>(fence); | |
151 fGLDeleteSync(glsync); | |
152 } | |
OLD | NEW |