OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2011 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 | |
9 #include "NullGLContext.h" | |
10 #include "gl/GrGLTestInterface.h" | |
11 #include "gl/GrGLDefines.h" | |
12 #include "gl/GrGLInterface.h" | |
13 #include "gl/GrGLTypes.h" | |
14 #include "SkMutex.h" | |
15 #include "SkTDArray.h" | |
16 | |
17 namespace { | |
18 | |
19 class BufferObj { | |
20 public: | |
21 BufferObj(GrGLuint id) : fID(id), fDataPtr(nullptr), fSize(0), fMapped(false
) {} | |
22 ~BufferObj() { delete[] fDataPtr; } | |
23 | |
24 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { | |
25 if (fDataPtr) { | |
26 SkASSERT(0 != fSize); | |
27 delete[] fDataPtr; | |
28 } | |
29 | |
30 fSize = size; | |
31 fDataPtr = new char[size]; | |
32 } | |
33 | |
34 GrGLuint id() const { return fID; } | |
35 GrGLchar* dataPtr() { return fDataPtr; } | |
36 GrGLsizeiptr size() const { return fSize; } | |
37 | |
38 void setMapped(bool mapped) { fMapped = mapped; } | |
39 bool mapped() const { return fMapped; } | |
40 | |
41 private: | |
42 GrGLuint fID; | |
43 GrGLchar* fDataPtr; | |
44 GrGLsizeiptr fSize; // size in bytes | |
45 bool fMapped; | |
46 }; | |
47 | |
48 // This class maintains a sparsely populated array of buffer pointers. | |
49 class BufferManager { | |
50 public: | |
51 BufferManager() : fFreeListHead(kFreeListEnd) {} | |
52 | |
53 ~BufferManager() { | |
54 // nullptr out the entries that are really free list links rather than p
trs before deleting. | |
55 intptr_t curr = fFreeListHead; | |
56 while (kFreeListEnd != curr) { | |
57 intptr_t next = reinterpret_cast<intptr_t>(fBuffers[SkToS32(curr)]); | |
58 fBuffers[SkToS32(curr)] = nullptr; | |
59 curr = next; | |
60 } | |
61 | |
62 fBuffers.deleteAll(); | |
63 } | |
64 | |
65 BufferObj* lookUp(GrGLuint id) { | |
66 BufferObj* buffer = fBuffers[id]; | |
67 SkASSERT(buffer && buffer->id() == id); | |
68 return buffer; | |
69 } | |
70 | |
71 BufferObj* create() { | |
72 GrGLuint id; | |
73 BufferObj* buffer; | |
74 | |
75 if (kFreeListEnd == fFreeListHead) { | |
76 // no free slots - create a new one | |
77 id = fBuffers.count(); | |
78 buffer = new BufferObj(id); | |
79 *fBuffers.append() = buffer; | |
80 } else { | |
81 // grab the head of the free list and advance the head to the next f
ree slot. | |
82 id = static_cast<GrGLuint>(fFreeListHead); | |
83 fFreeListHead = reinterpret_cast<intptr_t>(fBuffers[id]); | |
84 | |
85 buffer = new BufferObj(id); | |
86 fBuffers[id] = buffer; | |
87 } | |
88 | |
89 return buffer; | |
90 } | |
91 | |
92 void free(BufferObj* buffer) { | |
93 SkASSERT(fBuffers.count() > 0); | |
94 | |
95 GrGLuint id = buffer->id(); | |
96 delete buffer; | |
97 | |
98 fBuffers[id] = reinterpret_cast<BufferObj*>(fFreeListHead); | |
99 fFreeListHead = id; | |
100 } | |
101 | |
102 private: | |
103 static const intptr_t kFreeListEnd = -1; | |
104 // Index of the first entry of fBuffers in the free list. Free slots in fBuf
fers are indices to | |
105 // the next free slot. The last free slot has a value of kFreeListEnd. | |
106 intptr_t fFreeListHead; | |
107 SkTDArray<BufferObj*> fBuffers; | |
108 }; | |
109 | |
110 /** Null interface implementation */ | |
111 class NullInterface : public GrGLTestInterface { | |
112 public: | |
113 NullInterface() | |
114 : fCurrArrayBuffer(0) | |
115 , fCurrElementArrayBuffer(0) | |
116 , fCurrPixelPackBuffer(0) | |
117 , fCurrPixelUnpackBuffer(0) | |
118 , fCurrShaderID(0) | |
119 , fCurrGenericID(0) | |
120 , fCurrUniformLocation(0) { | |
121 this->init(kGL_GrGLStandard); | |
122 } | |
123 | |
124 GrGLenum checkFramebufferStatus(GrGLenum target) override { | |
125 return GR_GL_FRAMEBUFFER_COMPLETE; | |
126 } | |
127 | |
128 GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override { | |
129 for (int i = 0; i < n; ++i) { | |
130 BufferObj* buffer = fBufferManager.create(); | |
131 ids[i] = buffer->id(); | |
132 } | |
133 } | |
134 | |
135 GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data
, | |
136 GrGLenum usage) override { | |
137 GrGLuint id = 0; | |
138 | |
139 switch (target) { | |
140 case GR_GL_ARRAY_BUFFER: | |
141 id = fCurrArrayBuffer; | |
142 break; | |
143 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
144 id = fCurrElementArrayBuffer; | |
145 break; | |
146 case GR_GL_PIXEL_PACK_BUFFER: | |
147 id = fCurrPixelPackBuffer; | |
148 break; | |
149 case GR_GL_PIXEL_UNPACK_BUFFER: | |
150 id = fCurrPixelUnpackBuffer; | |
151 break; | |
152 default: | |
153 SkFAIL("Unexpected target to nullGLBufferData"); | |
154 break; | |
155 } | |
156 | |
157 if (id > 0) { | |
158 BufferObj* buffer = fBufferManager.lookUp(id); | |
159 buffer->allocate(size, (const GrGLchar*) data); | |
160 } | |
161 } | |
162 | |
163 GrGLuint createProgram() override { | |
164 return ++fCurrProgramID; | |
165 } | |
166 | |
167 GrGLuint createShader(GrGLenum type) override { | |
168 return ++fCurrShaderID; | |
169 } | |
170 | |
171 GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) override { | |
172 switch (target) { | |
173 case GR_GL_ARRAY_BUFFER: | |
174 fCurrArrayBuffer = buffer; | |
175 break; | |
176 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
177 fCurrElementArrayBuffer = buffer; | |
178 break; | |
179 case GR_GL_PIXEL_PACK_BUFFER: | |
180 fCurrPixelPackBuffer = buffer; | |
181 break; | |
182 case GR_GL_PIXEL_UNPACK_BUFFER: | |
183 fCurrPixelUnpackBuffer = buffer; | |
184 break; | |
185 } | |
186 } | |
187 | |
188 // deleting a bound buffer has the side effect of binding 0 | |
189 GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override { | |
190 for (int i = 0; i < n; ++i) { | |
191 if (ids[i] == fCurrArrayBuffer) { | |
192 fCurrArrayBuffer = 0; | |
193 } | |
194 if (ids[i] == fCurrElementArrayBuffer) { | |
195 fCurrElementArrayBuffer = 0; | |
196 } | |
197 if (ids[i] == fCurrPixelPackBuffer) { | |
198 fCurrPixelPackBuffer = 0; | |
199 } | |
200 if (ids[i] == fCurrPixelUnpackBuffer) { | |
201 fCurrPixelUnpackBuffer = 0; | |
202 } | |
203 | |
204 BufferObj* buffer = fBufferManager.lookUp(ids[i]); | |
205 fBufferManager.free(buffer); | |
206 } | |
207 } | |
208 | |
209 GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override { | |
210 this->genGenericIds(n, framebuffers); | |
211 } | |
212 | |
213 GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericI
ds(n, ids); } | |
214 | |
215 GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override { | |
216 this->genGenericIds(n, renderbuffers); | |
217 } | |
218 | |
219 GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override { | |
220 this->genGenericIds(n, textures); | |
221 } | |
222 | |
223 GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override { | |
224 this->genGenericIds(n, arrays); | |
225 } | |
226 | |
227 GrGLenum getError() override { return GR_GL_NO_ERROR; } | |
228 | |
229 GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override { | |
230 // TODO: remove from Ganesh the #defines for gets we don't use. | |
231 // We would like to minimize gets overall due to performance issues | |
232 switch (pname) { | |
233 case GR_GL_CONTEXT_PROFILE_MASK: | |
234 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; | |
235 break; | |
236 case GR_GL_STENCIL_BITS: | |
237 *params = 8; | |
238 break; | |
239 case GR_GL_SAMPLES: | |
240 *params = 1; | |
241 break; | |
242 case GR_GL_FRAMEBUFFER_BINDING: | |
243 *params = 0; | |
244 break; | |
245 case GR_GL_VIEWPORT: | |
246 params[0] = 0; | |
247 params[1] = 0; | |
248 params[2] = 800; | |
249 params[3] = 600; | |
250 break; | |
251 case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: | |
252 case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS: | |
253 case GR_GL_MAX_TEXTURE_IMAGE_UNITS: | |
254 case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: | |
255 *params = 8; | |
256 break; | |
257 case GR_GL_MAX_TEXTURE_COORDS: | |
258 *params = 8; | |
259 break; | |
260 case GR_GL_MAX_VERTEX_UNIFORM_VECTORS: | |
261 *params = kDefaultMaxVertexUniformVectors; | |
262 break; | |
263 case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS: | |
264 *params = kDefaultMaxFragmentUniformVectors; | |
265 break; | |
266 case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: | |
267 *params = 16 * 4; | |
268 break; | |
269 case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS: | |
270 *params = 0; | |
271 break; | |
272 case GR_GL_COMPRESSED_TEXTURE_FORMATS: | |
273 break; | |
274 case GR_GL_MAX_TEXTURE_SIZE: | |
275 *params = 8192; | |
276 break; | |
277 case GR_GL_MAX_RENDERBUFFER_SIZE: | |
278 *params = 8192; | |
279 break; | |
280 case GR_GL_MAX_SAMPLES: | |
281 *params = 32; | |
282 break; | |
283 case GR_GL_MAX_VERTEX_ATTRIBS: | |
284 *params = kDefaultMaxVertexAttribs; | |
285 break; | |
286 case GR_GL_MAX_VARYING_VECTORS: | |
287 *params = kDefaultMaxVaryingVectors; | |
288 break; | |
289 case GR_GL_NUM_EXTENSIONS: { | |
290 GrGLint i = 0; | |
291 while (kExtensions[i++]); | |
292 *params = i; | |
293 break; | |
294 } | |
295 default: | |
296 SkFAIL("Unexpected pname to GetIntegerv"); | |
297 } | |
298 } | |
299 | |
300 GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) ove
rride { | |
301 this->getShaderOrProgramiv(program, pname, params); | |
302 } | |
303 | |
304 GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* l
ength, | |
305 char* infolog) override { | |
306 this->getInfoLog(program, bufsize, length, infolog); | |
307 } | |
308 | |
309 GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) ov
erride { | |
310 val[0] = val[1] = 0.5f; | |
311 } | |
312 | |
313 GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) over
ride { | |
314 switch (pname) { | |
315 case GR_GL_CURRENT_QUERY: | |
316 *params = 0; | |
317 break; | |
318 case GR_GL_QUERY_COUNTER_BITS: | |
319 *params = 32; | |
320 break; | |
321 default: | |
322 SkFAIL("Unexpected pname passed GetQueryiv."); | |
323 } | |
324 } | |
325 | |
326 GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params)
override { | |
327 this->queryResult(id, pname, params); | |
328 } | |
329 | |
330 GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) over
ride { | |
331 this->queryResult(id, pname, params); | |
332 } | |
333 | |
334 GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params
) override { | |
335 this->queryResult(id, pname, params); | |
336 } | |
337 | |
338 GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) ov
erride { | |
339 this->queryResult(id, pname, params); | |
340 } | |
341 | |
342 GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) overr
ide { | |
343 this->getShaderOrProgramiv(shader, pname, params); | |
344 } | |
345 | |
346 GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* len
gth, | |
347 char* infolog) override { | |
348 this->getInfoLog(shader, bufsize, length, infolog); | |
349 } | |
350 | |
351 const GrGLubyte* getString(GrGLenum name) override { | |
352 switch (name) { | |
353 case GR_GL_EXTENSIONS: | |
354 return CombinedExtensionString(); | |
355 case GR_GL_VERSION: | |
356 return (const GrGLubyte*)"4.0 Null GL"; | |
357 case GR_GL_SHADING_LANGUAGE_VERSION: | |
358 return (const GrGLubyte*)"4.20.8 Null GLSL"; | |
359 case GR_GL_VENDOR: | |
360 return (const GrGLubyte*)"Null Vendor"; | |
361 case GR_GL_RENDERER: | |
362 return (const GrGLubyte*)"The Null (Non-)Renderer"; | |
363 default: | |
364 SkFAIL("Unexpected name passed to GetString"); | |
365 return nullptr; | |
366 } | |
367 } | |
368 | |
369 const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override { | |
370 switch (name) { | |
371 case GR_GL_EXTENSIONS: { | |
372 GrGLint count; | |
373 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count); | |
374 if ((GrGLint)i <= count) { | |
375 return (const GrGLubyte*) kExtensions[i]; | |
376 } else { | |
377 return nullptr; | |
378 } | |
379 } | |
380 default: | |
381 SkFAIL("Unexpected name passed to GetStringi"); | |
382 return nullptr; | |
383 } | |
384 } | |
385 | |
386 GrGLint getUniformLocation(GrGLuint program, const char* name) override { | |
387 return ++fCurrUniformLocation; | |
388 } | |
389 | |
390 GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr le
ngth, | |
391 GrGLbitfield access) override { | |
392 GrGLuint id = 0; | |
393 switch (target) { | |
394 case GR_GL_ARRAY_BUFFER: | |
395 id = fCurrArrayBuffer; | |
396 break; | |
397 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
398 id = fCurrElementArrayBuffer; | |
399 break; | |
400 case GR_GL_PIXEL_PACK_BUFFER: | |
401 id = fCurrPixelPackBuffer; | |
402 break; | |
403 case GR_GL_PIXEL_UNPACK_BUFFER: | |
404 id = fCurrPixelUnpackBuffer; | |
405 break; | |
406 } | |
407 | |
408 if (id > 0) { | |
409 // We just ignore the offset and length here. | |
410 BufferObj* buffer = fBufferManager.lookUp(id); | |
411 SkASSERT(!buffer->mapped()); | |
412 buffer->setMapped(true); | |
413 return buffer->dataPtr(); | |
414 } | |
415 return nullptr; | |
416 } | |
417 | |
418 GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override { | |
419 GrGLuint id = 0; | |
420 switch (target) { | |
421 case GR_GL_ARRAY_BUFFER: | |
422 id = fCurrArrayBuffer; | |
423 break; | |
424 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
425 id = fCurrElementArrayBuffer; | |
426 break; | |
427 case GR_GL_PIXEL_PACK_BUFFER: | |
428 id = fCurrPixelPackBuffer; | |
429 break; | |
430 case GR_GL_PIXEL_UNPACK_BUFFER: | |
431 id = fCurrPixelUnpackBuffer; | |
432 break; | |
433 } | |
434 | |
435 if (id > 0) { | |
436 BufferObj* buffer = fBufferManager.lookUp(id); | |
437 SkASSERT(!buffer->mapped()); | |
438 buffer->setMapped(true); | |
439 return buffer->dataPtr(); | |
440 } | |
441 | |
442 SkASSERT(false); | |
443 return nullptr; // no buffer bound to target | |
444 } | |
445 | |
446 GrGLboolean unmapBuffer(GrGLenum target) override { | |
447 GrGLuint id = 0; | |
448 switch (target) { | |
449 case GR_GL_ARRAY_BUFFER: | |
450 id = fCurrArrayBuffer; | |
451 break; | |
452 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
453 id = fCurrElementArrayBuffer; | |
454 break; | |
455 case GR_GL_PIXEL_PACK_BUFFER: | |
456 id = fCurrPixelPackBuffer; | |
457 break; | |
458 case GR_GL_PIXEL_UNPACK_BUFFER: | |
459 id = fCurrPixelUnpackBuffer; | |
460 break; | |
461 } | |
462 if (id > 0) { | |
463 BufferObj* buffer = fBufferManager.lookUp(id); | |
464 SkASSERT(buffer->mapped()); | |
465 buffer->setMapped(false); | |
466 return GR_GL_TRUE; | |
467 } | |
468 | |
469 GrAlwaysAssert(false); | |
470 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION; | |
471 } | |
472 | |
473 GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* para
ms) override { | |
474 switch (pname) { | |
475 case GR_GL_BUFFER_MAPPED: { | |
476 *params = GR_GL_FALSE; | |
477 GrGLuint id = 0; | |
478 switch (target) { | |
479 case GR_GL_ARRAY_BUFFER: | |
480 id = fCurrArrayBuffer; | |
481 break; | |
482 case GR_GL_ELEMENT_ARRAY_BUFFER: | |
483 id = fCurrElementArrayBuffer; | |
484 break; | |
485 case GR_GL_PIXEL_PACK_BUFFER: | |
486 id = fCurrPixelPackBuffer; | |
487 break; | |
488 case GR_GL_PIXEL_UNPACK_BUFFER: | |
489 id = fCurrPixelUnpackBuffer; | |
490 break; | |
491 } | |
492 if (id > 0) { | |
493 BufferObj* buffer = fBufferManager.lookUp(id); | |
494 if (buffer->mapped()) { | |
495 *params = GR_GL_TRUE; | |
496 } | |
497 } | |
498 break; } | |
499 default: | |
500 SkFAIL("Unexpected pname to GetBufferParamateriv"); | |
501 break; | |
502 } | |
503 }; | |
504 | |
505 private: | |
506 BufferManager fBufferManager; | |
507 GrGLuint fCurrArrayBuffer; | |
508 GrGLuint fCurrElementArrayBuffer; | |
509 GrGLuint fCurrPixelPackBuffer; | |
510 GrGLuint fCurrPixelUnpackBuffer; | |
511 GrGLuint fCurrProgramID; | |
512 GrGLuint fCurrShaderID; | |
513 GrGLuint fCurrGenericID; | |
514 GrGLuint fCurrUniformLocation; | |
515 | |
516 // the OpenGLES 2.0 spec says this must be >= 128 | |
517 static const GrGLint kDefaultMaxVertexUniformVectors = 128; | |
518 | |
519 // the OpenGLES 2.0 spec says this must be >=16 | |
520 static const GrGLint kDefaultMaxFragmentUniformVectors = 16; | |
521 | |
522 // the OpenGLES 2.0 spec says this must be >= 8 | |
523 static const GrGLint kDefaultMaxVertexAttribs = 8; | |
524 | |
525 // the OpenGLES 2.0 spec says this must be >= 8 | |
526 static const GrGLint kDefaultMaxVaryingVectors = 8; | |
527 | |
528 static const char* kExtensions[]; | |
529 | |
530 static const GrGLubyte* CombinedExtensionString() { | |
531 static SkString gExtString; | |
532 static SkMutex gMutex; | |
533 gMutex.acquire(); | |
534 if (0 == gExtString.size()) { | |
535 int i = 0; | |
536 while (kExtensions[i]) { | |
537 if (i > 0) { | |
538 gExtString.append(" "); | |
539 } | |
540 gExtString.append(kExtensions[i]); | |
541 ++i; | |
542 } | |
543 } | |
544 gMutex.release(); | |
545 return (const GrGLubyte*) gExtString.c_str(); | |
546 } | |
547 | |
548 GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) { | |
549 for (int i = 0; i < n; ++i) { | |
550 ids[i] = ++fCurrGenericID; | |
551 } | |
552 } | |
553 | |
554 GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length, | |
555 char* infolog) { | |
556 if (length) { | |
557 *length = 0; | |
558 } | |
559 if (bufsize > 0) { | |
560 *infolog = 0; | |
561 } | |
562 } | |
563 | |
564 GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* par
ams) { | |
565 switch (pname) { | |
566 case GR_GL_LINK_STATUS: // fallthru | |
567 case GR_GL_COMPILE_STATUS: | |
568 *params = GR_GL_TRUE; | |
569 break; | |
570 case GR_GL_INFO_LOG_LENGTH: | |
571 *params = 0; | |
572 break; | |
573 // we don't expect any other pnames | |
574 default: | |
575 SkFAIL("Unexpected pname to GetProgramiv"); | |
576 break; | |
577 } | |
578 } | |
579 | |
580 template <typename T> | |
581 void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) { | |
582 switch (pname) { | |
583 case GR_GL_QUERY_RESULT_AVAILABLE: | |
584 *params = GR_GL_TRUE; | |
585 break; | |
586 case GR_GL_QUERY_RESULT: | |
587 *params = 0; | |
588 break; | |
589 default: | |
590 SkFAIL("Unexpected pname passed to GetQueryObject."); | |
591 break; | |
592 } | |
593 } | |
594 | |
595 typedef GrGLTestInterface INHERITED; | |
596 }; | |
597 | |
598 const char* NullInterface::kExtensions[] = { | |
599 "GL_ARB_framebuffer_object", | |
600 "GL_ARB_blend_func_extended", | |
601 "GL_ARB_timer_query", | |
602 "GL_ARB_draw_buffers", | |
603 "GL_ARB_occlusion_query", | |
604 "GL_EXT_stencil_wrap", | |
605 nullptr, // signifies the end of the array. | |
606 }; | |
607 | |
608 class NullGLContext : public sk_gpu_test::GLContext { | |
609 public: | |
610 NullGLContext() { this->init(new NullInterface); } | |
611 ~NullGLContext() override { this->teardown(); } | |
612 | |
613 private: | |
614 void onPlatformMakeCurrent() const override {}; | |
615 void onPlatformSwapBuffers() const override {} | |
616 GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nu
llptr; } | |
617 }; | |
618 } // anonymous namespace | |
619 | |
620 namespace sk_gpu_test { | |
621 GLContext* CreateNullGLContext() { | |
622 GLContext* ctx = new NullGLContext(); | |
623 if (ctx->isValid()) { | |
624 return ctx; | |
625 } | |
626 delete ctx; | |
627 return nullptr; | |
628 } | |
629 } // namespace sk_gpu_test | |
630 | |
OLD | NEW |