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