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