OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2013 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 #include "gl/SkGLContext.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 waitFence(SkPlatformGpuFence fence, bool flush) 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 }; | |
39 | |
40 SkGLContext::SkGLContext() | |
41 : fCurrentFenceIdx(0) { | |
42 memset(fFrameFences, 0, sizeof(fFrameFences)); | |
43 } | |
44 | |
45 SkGLContext::~SkGLContext() { | |
46 // Subclass should call teardown. | |
47 #ifdef SK_DEBUG | |
48 for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) { | |
49 SkASSERT(0 == fFrameFences[i]); | |
50 } | |
51 #endif | |
52 SkASSERT(nullptr == fGL.get()); | |
53 SkASSERT(nullptr == fFenceSync.get()); | |
54 } | |
55 | |
56 void SkGLContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) { | |
57 SkASSERT(!fGL.get()); | |
58 fGL.reset(gl); | |
59 fFenceSync.reset(fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this
)); | |
60 } | |
61 | |
62 void SkGLContext::teardown() { | |
63 if (fFenceSync) { | |
64 for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) { | |
65 if (fFrameFences[i]) { | |
66 fFenceSync->deleteFence(fFrameFences[i]); | |
67 fFrameFences[i] = 0; | |
68 } | |
69 } | |
70 fFenceSync.reset(nullptr); | |
71 } | |
72 | |
73 fGL.reset(nullptr); | |
74 } | |
75 | |
76 void SkGLContext::makeCurrent() const { | |
77 this->onPlatformMakeCurrent(); | |
78 } | |
79 | |
80 void SkGLContext::swapBuffers() { | |
81 this->onPlatformSwapBuffers(); | |
82 } | |
83 | |
84 void SkGLContext::waitOnSyncOrSwap() { | |
85 if (!fFenceSync) { | |
86 // Fallback on the platform SwapBuffers method for synchronization. This
may have no effect. | |
87 this->swapBuffers(); | |
88 return; | |
89 } | |
90 | |
91 if (fFrameFences[fCurrentFenceIdx]) { | |
92 if (!fFenceSync->waitFence(fFrameFences[fCurrentFenceIdx], true)) { | |
93 SkDebugf("WARNING: Wait failed for fence sync. Timings might not be
accurate.\n"); | |
94 } | |
95 fFenceSync->deleteFence(fFrameFences[fCurrentFenceIdx]); | |
96 } | |
97 | |
98 fFrameFences[fCurrentFenceIdx] = fFenceSync->insertFence(); | |
99 fCurrentFenceIdx = (fCurrentFenceIdx + 1) % SK_ARRAY_COUNT(fFrameFences); | |
100 } | |
101 | |
102 void SkGLContext::testAbandon() { | |
103 if (fGL) { | |
104 fGL->abandon(); | |
105 } | |
106 if (fFenceSync) { | |
107 memset(fFrameFences, 0, sizeof(fFrameFences)); | |
108 } | |
109 } | |
110 | |
111 SkGLContext::GLFenceSync* SkGLContext::GLFenceSync::CreateIfSupported(const SkGL
Context* ctx) { | |
112 SkAutoTDelete<GLFenceSync> ret(new GLFenceSync); | |
113 | |
114 if (kGL_GrGLStandard == ctx->gl()->fStandard) { | |
115 const GrGLubyte* versionStr; | |
116 SK_GL_RET(*ctx, versionStr, GetString(GR_GL_VERSION)); | |
117 GrGLVersion version = GrGLGetVersionFromString(reinterpret_cast<const ch
ar*>(versionStr)); | |
118 if (version < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync"))
{ | |
119 return nullptr; | |
120 } | |
121 ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( | |
122 ctx->onPlatformGetProcAddress("glFenceSync")); | |
123 ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( | |
124 ctx->onPlatformGetProcAddress("glClientWaitSync")); | |
125 ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( | |
126 ctx->onPlatformGetProcAddress("glDeleteSync")); | |
127 } else { | |
128 if (!ctx->gl()->hasExtension("GL_APPLE_sync")) { | |
129 return nullptr; | |
130 } | |
131 ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( | |
132 ctx->onPlatformGetProcAddress("glFenceSyncAPPLE")); | |
133 ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( | |
134 ctx->onPlatformGetProcAddress("glClientWaitSyncAPPLE")); | |
135 ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( | |
136 ctx->onPlatformGetProcAddress("glDeleteSyncAPPLE")); | |
137 } | |
138 | |
139 if (!ret->fGLFenceSync || !ret->fGLClientWaitSync || !ret->fGLDeleteSync) { | |
140 return nullptr; | |
141 } | |
142 | |
143 return ret.release(); | |
144 } | |
145 | |
146 SkPlatformGpuFence SkGLContext::GLFenceSync::insertFence() const { | |
147 return fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | |
148 } | |
149 | |
150 bool SkGLContext::GLFenceSync::waitFence(SkPlatformGpuFence fence, bool flush) c
onst { | |
151 GLsync glsync = static_cast<GLsync>(fence); | |
152 return GL_WAIT_FAILED != fGLClientWaitSync(glsync, flush ? GL_SYNC_FLUSH_COM
MANDS_BIT : 0, -1); | |
153 } | |
154 | |
155 void SkGLContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const { | |
156 GLsync glsync = static_cast<GLsync>(fence); | |
157 fGLDeleteSync(glsync); | |
158 } | |
159 | |
160 GrGLint SkGLContext::createTextureRectangle(int width, int height, GrGLenum inte
rnalFormat, | |
161 GrGLenum externalFormat, GrGLenum ex
ternalType, | |
162 GrGLvoid* data) { | |
163 if (!(kGL_GrGLStandard == fGL->fStandard && GrGLGetVersion(fGL) >= GR_GL_VER
(3, 1)) && | |
164 !fGL->fExtensions.has("GL_ARB_texture_rectangle")) { | |
165 return 0; | |
166 } | |
167 | |
168 if (GrGLGetGLSLVersion(fGL) < GR_GLSL_VER(1, 40)) { | |
169 return 0; | |
170 } | |
171 | |
172 GrGLuint id; | |
173 GR_GL_CALL(fGL, GenTextures(1, &id)); | |
174 GR_GL_CALL(fGL, BindTexture(GR_GL_TEXTURE_RECTANGLE, id)); | |
175 GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MAG_FIL
TER, | |
176 GR_GL_NEAREST)); | |
177 GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MIN_FIL
TER, | |
178 GR_GL_NEAREST)); | |
179 GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_S, | |
180 GR_GL_CLAMP_TO_EDGE)); | |
181 GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_T, | |
182 GR_GL_CLAMP_TO_EDGE)); | |
183 GR_GL_CALL(fGL, TexImage2D(GR_GL_TEXTURE_RECTANGLE, 0, internalFormat, width
, height, 0, | |
184 externalFormat, externalType, data)); | |
185 return id; | |
186 } | |
OLD | NEW |