blob: 3b2a376e849cd75edd040e607df45a21e923e902 [file] [log] [blame]
robertphillips@google.com0da37192012-03-19 14:42:13 +00001
2/*
3 * Copyright 2012 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
10#include "gl/GrGLInterface.h"
11
12#include "SkTArray.h"
13
14// the OpenGLES 2.0 spec says this must be >= 2
15static const GrGLint kDefaultMaxTextureUnits = 8;
16
17////////////////////////////////////////////////////////////////////////////////
18// This object is used to track the OpenGL objects. We don't use real
19// reference counting (i.e., we don't free the objects when their ref count
20// goes to 0) so that we can detect invalid memory accesses. The refs we
21// are tracking in this class are actually OpenGL's references to the objects
22// not "ours"
23// Each object also gets a unique globally identifying ID
24class GrFakeRefObj
25{
26public:
27 GrFakeRefObj(GrGLuint ID)
28 : fRef(0)
29 , fID(ID)
30 , fMarkedForDeletion(false)
31 , fDeleted(false) {
32 }
33 virtual ~GrFakeRefObj() {};
34
35 void ref() { fRef++; }
36 void unref() {
37 fRef--;
38 // often in OpenGL a given object may still be in use when the
39 // delete call is made. In these cases the object is marked
40 // for deletion and then freed when it is no longer in use
41 if (0 == fRef && fMarkedForDeletion) {
42 this->deleteAction();
43 }
44 }
45 int getRefCount() const { return fRef; }
46
47 GrGLuint getID() const { return fID; }
48
49 void setMarkedForDeletion() { fMarkedForDeletion = true; }
50 bool getMarkedForDeletion() const { return fMarkedForDeletion; }
51
52 // setDeleted should only ever appear in deleteAction methods!
53 void setDeleted() { fDeleted = true; }
54 bool getDeleted() const { return fDeleted; }
55
56 // The deleteAction fires if the object has been marked for deletion but
57 // couldn't be deleted earlier due to refs
58 virtual void deleteAction() = 0;
59
60protected:
61private:
62 int fRef;
63 GrGLuint fID;
64 bool fMarkedForDeletion;
65 // The deleted flag is only set when OpenGL thinks the object is deleted
66 // It is obviously still allocated w/in this framework
67 bool fDeleted;
68};
69
70////////////////////////////////////////////////////////////////////////////////
71class GrBufferObj : public GrFakeRefObj
72{
73public:
74 GrBufferObj(GrGLuint ID)
75 : GrFakeRefObj(ID)
76 , fDataPtr(NULL)
77 , fMapped(false)
78 , fBound(false)
79 , fSize(0)
80 , fUsage(GR_GL_STATIC_DRAW) {
81 }
82 virtual ~GrBufferObj() {
83 delete[] fDataPtr;
84 }
85
86 void access() {
87 // cannot access the buffer if it is currently mapped
88 GrAlwaysAssert(!fMapped);
89 }
90
91 void setMapped() { fMapped = true; }
92 void resetMapped() { fMapped = false; }
93 bool getMapped() const { return fMapped; }
94
95 void setBound() { fBound = true; }
96 void resetBound() { fBound = false; }
97 bool getBound() const { return fBound; }
98
99 void allocate(GrGLint size, const GrGLvoid *dataPtr) {
100 GrAlwaysAssert(size >= 0);
101
102 // delete pre-existing data
robertphillips@google.com0ffc56f2012-03-21 13:05:04 +0000103 delete fDataPtr;
robertphillips@google.com0da37192012-03-19 14:42:13 +0000104
105 fSize = size;
robertphillips@google.comd41a1dc2012-03-19 17:33:58 +0000106 fDataPtr = new char[size];
robertphillips@google.com0da37192012-03-19 14:42:13 +0000107 if (dataPtr) {
108 memcpy(fDataPtr, dataPtr, fSize);
109 }
110 // TODO: w/ no dataPtr the data is unitialized - this could be tracked
111 }
112 GrGLint getSize() const { return fSize; }
robertphillips@google.comd41a1dc2012-03-19 17:33:58 +0000113 GrGLvoid *getDataPtr() { return fDataPtr; }
robertphillips@google.com0da37192012-03-19 14:42:13 +0000114
115 GrGLint getUsage() const { return fUsage; }
116 void setUsage(GrGLint usage) { fUsage = usage; }
117
118 virtual void deleteAction() SK_OVERRIDE {
119
120 // buffers are automatically unmapped when deleted
121 this->resetMapped();
122 this->setDeleted();
123 }
124
125
126protected:
127private:
128
robertphillips@google.comd41a1dc2012-03-19 17:33:58 +0000129 GrGLvoid* fDataPtr;
robertphillips@google.com0da37192012-03-19 14:42:13 +0000130 bool fMapped; // is the buffer object mapped via "glMapBuffer"?
131 bool fBound; // is the buffer object bound via "glBindBuffer"?
132 GrGLint fSize; // size in bytes
133 GrGLint fUsage; // one of: GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW
134
135 typedef GrFakeRefObj INHERITED;
136};
137
138
139////////////////////////////////////////////////////////////////////////////////
140class GrShaderObj : public GrFakeRefObj
141{
142public:
143 GrShaderObj(GrGLuint ID, GrGLenum type)
144 : GrFakeRefObj(ID)
145 , fType(type) {}
146
147 GrGLenum getType() { return fType; }
148
149 virtual void deleteAction() SK_OVERRIDE {
150
151 this->setDeleted();
152 }
153
154protected:
155private:
156 GrGLenum fType; // either GR_GL_VERTEX_SHADER or GR_GL_FRAGMENT_SHADER
157
158 typedef GrFakeRefObj INHERITED;
159};
160
161
162////////////////////////////////////////////////////////////////////////////////
163class GrProgramObj : public GrFakeRefObj
164{
165public:
166 GrProgramObj(GrGLuint ID)
167 : GrFakeRefObj(ID)
168 , fInUse(false) {}
169
170 void AttachShader(GrShaderObj *shader)
171 {
172 shader->ref();
173 fShaders.push_back(shader);
174 }
175
176 virtual void deleteAction() SK_OVERRIDE {
177
178 // shaders are automatically detached from a deleted program. They will only be
179 // deleted if they were marked for deletion by a prior call to glDeleteShader
180 for (int i = 0; i < fShaders.count(); ++i) {
181 fShaders[i]->unref();
182 }
183 fShaders.reset();
184
185 this->setDeleted();
186 }
187
188 void setInUse() { fInUse = true; }
189 bool getInUse() const { return fInUse; }
190
191protected:
192
193private:
194 SkTArray<GrShaderObj *> fShaders;
195 bool fInUse; // has this program been activated by a glUseProgram call?
196
197 typedef GrFakeRefObj INHERITED;
198};
199
200////////////////////////////////////////////////////////////////////////////////
201// This is the main debugging object. It is a singleton and keeps track of
202// all the other debug objects.
203class GrDebugGL
204{
205public:
206 // TODO: merge findBuffer, findShader & findProgram??
207 GrBufferObj *findBuffer(GrGLuint ID)
208 {
209 GrFakeRefObj *obj = this->findObject(ID);
210 if (NULL == obj) {
211 return NULL;
212 }
213
214 return reinterpret_cast<GrBufferObj *>(obj);
215 }
216
217 GrShaderObj *findShader(GrGLuint ID)
218 {
219 GrFakeRefObj *obj = this->findObject(ID);
220 if (NULL == obj) {
221 return NULL;
222 }
223
224 return reinterpret_cast<GrShaderObj *>(obj);
225 }
226
227 GrProgramObj *findProgram(GrGLuint ID)
228 {
229 GrFakeRefObj *obj = this->findObject(ID);
230 if (NULL == obj) {
231 return NULL;
232 }
233
234 return reinterpret_cast<GrProgramObj *>(obj);
235 }
236
237 // TODO: merge createBuffer, createShader, createProgram??
238 GrBufferObj *createBuffer()
239 {
240 GrBufferObj *buffer = new GrBufferObj(++fNextID);
241
242 fObjects.push_back(buffer);
243
244 return buffer;
245 }
246
247 GrShaderObj *createShader(GrGLenum type)
248 {
249 GrShaderObj *shader = new GrShaderObj(++fNextID, type);
250
251 fObjects.push_back(shader);
252
253 return shader;
254 }
255
256 GrProgramObj *createProgram()
257 {
258 GrProgramObj *program = new GrProgramObj(++fNextID);
259
260 fObjects.push_back(program);
261
262 return program;
263 }
264
265 GrFakeRefObj *findObject(GrGLuint ID)
266 {
267 for (int i = 0; i < fObjects.count(); ++i) {
268 if (fObjects[i]->getID() == ID) {
269 // The application shouldn't be accessing objects
270 // that (as far as OpenGL knows) were already deleted
271 GrAlwaysAssert(!fObjects[i]->getDeleted());
272 GrAlwaysAssert(!fObjects[i]->getMarkedForDeletion());
273 return fObjects[i];
274 }
275 }
276
277 return NULL;
278 }
279
280
281 void setMaxTextureUnits(GrGLuint maxTextureUnits) { fMaxTextureUnits = maxTextureUnits; }
282 GrGLuint getMaxTextureUnits() const { return fMaxTextureUnits; }
283
284 void setCurTextureUnit(GrGLuint curTextureUnit) { fCurTextureUnit = curTextureUnit; }
285 GrGLuint getCurTextureUnit() const { return fCurTextureUnit; }
286
287 void setArrayBuffer(GrBufferObj *arrayBuffer) { fArrayBuffer = arrayBuffer; }
288 GrBufferObj *getArrayBuffer() { return fArrayBuffer; }
289
290 void setElementArrayBuffer(GrBufferObj *elementArrayBuffer) { fElementArrayBuffer = elementArrayBuffer; }
291 GrBufferObj *getElementArrayBuffer() { return fElementArrayBuffer; }
292
293 static GrDebugGL *getInstance()
294 {
295// static GrDebugGL Obj;
296
297 return &Obj;
298 }
299
300 void report() const {
301 for (int i = 0; i < fObjects.count(); ++i) {
302 GrAlwaysAssert(fObjects[i]->getDeleted());
303 }
304 }
305
306protected:
307
308private:
309 GrGLuint fMaxTextureUnits;
310 GrGLuint fCurTextureUnit;
311 GrBufferObj * fArrayBuffer;
312 GrBufferObj * fElementArrayBuffer;
313
314 static int fNextID; // source for globally unique IDs
315
316 static GrDebugGL Obj;
317
318 // global store of all objects
319 SkTArray<GrFakeRefObj *> fObjects;
320
321 GrDebugGL()
322 : fMaxTextureUnits(kDefaultMaxTextureUnits)
323 , fCurTextureUnit(0)
324 , fArrayBuffer(NULL)
325 , fElementArrayBuffer(NULL)
326 {
327 }
328
329 ~GrDebugGL() {
330 this->report();
331
332 for (int i = 0; i < fObjects.count(); ++i) {
333 delete fObjects[i];
334 }
335 fObjects.reset();
336 fArrayBuffer = NULL;
337 fElementArrayBuffer = NULL;
338 }
339};
340
341int GrDebugGL::fNextID = 0;
342GrDebugGL GrDebugGL::Obj;
343
344////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comd41a1dc2012-03-19 17:33:58 +0000345GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture)
robertphillips@google.com0da37192012-03-19 14:42:13 +0000346{
robertphillips@google.comd41a1dc2012-03-19 17:33:58 +0000347
robertphillips@google.com0ffc56f2012-03-21 13:05:04 +0000348 GrAlwaysAssert(0 <= texture);
robertphillips@google.com0da37192012-03-19 14:42:13 +0000349// GrAlwaysAssert(texture < GrDebugGL::getInstance()->getMaxTextureUnits());
350
351 GrDebugGL::getInstance()->setCurTextureUnit(texture);
352}
353
354////////////////////////////////////////////////////////////////////////////////
355GrGLvoid GR_GL_FUNCTION_TYPE debugGLAttachShader(GrGLuint programID, GrGLuint shaderID)
356{
357 GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
358 GrAlwaysAssert(program);
359
360 GrShaderObj *shader = GrDebugGL::getInstance()->findShader(shaderID);
361 GrAlwaysAssert(shader);
362
363 program->AttachShader(shader);
364}
365
366GrGLvoid GR_GL_FUNCTION_TYPE debugGLBeginQuery(GrGLenum target, GrGLuint id) {}
367GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {}
368GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindTexture(GrGLenum target, GrGLuint texture) {}
369GrGLvoid GR_GL_FUNCTION_TYPE debugGLBlendColor(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha) {}
370GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFragDataLocation(GrGLuint program, GrGLuint colorNumber, const GrGLchar* name) {}
371GrGLvoid GR_GL_FUNCTION_TYPE debugGLBlendFunc(GrGLenum sfactor, GrGLenum dfactor) {}
372
373////////////////////////////////////////////////////////////////////////////////
374GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage)
375{
376 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
377 GrAlwaysAssert(size >= 0);
378 GrAlwaysAssert(GR_GL_STREAM_DRAW == usage || GR_GL_STATIC_DRAW == usage || GR_GL_DYNAMIC_DRAW == usage);
379
380 GrBufferObj *buffer = NULL;
381 switch (target) {
382 case GR_GL_ARRAY_BUFFER:
383 buffer = GrDebugGL::getInstance()->getArrayBuffer();
384 break;
385 case GR_GL_ELEMENT_ARRAY_BUFFER:
386 buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
387 break;
388 default:
389 GrCrash("Unexpected target to glBufferData");
390 break;
391 }
392
393 GrAlwaysAssert(buffer);
394 GrAlwaysAssert(buffer->getBound());
395
396 buffer->allocate(size, data);
397 buffer->setUsage(usage);
398}
399
400GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferSubData(GrGLenum target, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid* data) {}
401GrGLvoid GR_GL_FUNCTION_TYPE debugGLClear(GrGLbitfield mask) {}
402GrGLvoid GR_GL_FUNCTION_TYPE debugGLClearColor(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha) {}
403GrGLvoid GR_GL_FUNCTION_TYPE debugGLClearStencil(GrGLint s) {}
404GrGLvoid GR_GL_FUNCTION_TYPE debugGLColorMask(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha) {}
405GrGLvoid GR_GL_FUNCTION_TYPE debugGLCompileShader(GrGLuint shader) {}
406GrGLvoid GR_GL_FUNCTION_TYPE debugGLCompressedTexImage2D(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data) {}
407GrGLvoid GR_GL_FUNCTION_TYPE debugGLCullFace(GrGLenum mode) {}
408GrGLvoid GR_GL_FUNCTION_TYPE debugGLDepthMask(GrGLboolean flag) {}
409GrGLvoid GR_GL_FUNCTION_TYPE debugGLDisable(GrGLenum cap) {}
410GrGLvoid GR_GL_FUNCTION_TYPE debugGLDisableVertexAttribArray(GrGLuint index) {}
411GrGLvoid GR_GL_FUNCTION_TYPE debugGLDrawArrays(GrGLenum mode, GrGLint first, GrGLsizei count) {}
412GrGLvoid GR_GL_FUNCTION_TYPE debugGLDrawBuffer(GrGLenum mode) {}
413GrGLvoid GR_GL_FUNCTION_TYPE debugGLDrawBuffers(GrGLsizei n, const GrGLenum* bufs) {}
414GrGLvoid GR_GL_FUNCTION_TYPE debugGLDrawElements(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices) {}
415GrGLvoid GR_GL_FUNCTION_TYPE debugGLEnable(GrGLenum cap) {}
416GrGLvoid GR_GL_FUNCTION_TYPE debugGLEnableVertexAttribArray(GrGLuint index) {}
417GrGLvoid GR_GL_FUNCTION_TYPE debugGLEndQuery(GrGLenum target) {}
418GrGLvoid GR_GL_FUNCTION_TYPE debugGLFinish() {}
419GrGLvoid GR_GL_FUNCTION_TYPE debugGLFlush() {}
420GrGLvoid GR_GL_FUNCTION_TYPE debugGLFrontFace(GrGLenum mode) {}
421GrGLvoid GR_GL_FUNCTION_TYPE debugGLLineWidth(GrGLfloat width) {}
422GrGLvoid GR_GL_FUNCTION_TYPE debugGLLinkProgram(GrGLuint program) {}
423GrGLvoid GR_GL_FUNCTION_TYPE debugGLPixelStorei(GrGLenum pname, GrGLint param) {}
424GrGLvoid GR_GL_FUNCTION_TYPE debugGLQueryCounter(GrGLuint id, GrGLenum target) {}
425GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadBuffer(GrGLenum src) {}
426GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {}
427GrGLvoid GR_GL_FUNCTION_TYPE debugGLScissor(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
428GrGLvoid GR_GL_FUNCTION_TYPE debugGLShaderSource(GrGLuint shader, GrGLsizei count, const char** str, const GrGLint* length) {}
429GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask) {}
430GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilFuncSeparate(GrGLenum face, GrGLenum func, GrGLint ref, GrGLuint mask) {}
431GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilMask(GrGLuint mask) {}
432GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilMaskSeparate(GrGLenum face, GrGLuint mask) {}
433GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilOp(GrGLenum fail, GrGLenum zfail, GrGLenum zpass) {}
434GrGLvoid GR_GL_FUNCTION_TYPE debugGLStencilOpSeparate(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass) {}
435GrGLvoid GR_GL_FUNCTION_TYPE debugGLTexImage2D(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels) {}
436GrGLvoid GR_GL_FUNCTION_TYPE debugGLTexParameteri(GrGLenum target, GrGLenum pname, GrGLint param) {}
437GrGLvoid GR_GL_FUNCTION_TYPE debugGLTexStorage2D(GrGLenum target, GrGLsizei levels, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
438GrGLvoid GR_GL_FUNCTION_TYPE debugGLTexSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels) {}
439GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform1f(GrGLint location, GrGLfloat v0) {}
440GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform1i(GrGLint location, GrGLint v0) {}
441GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform1fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
442GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform1iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
443GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform2f(GrGLint location, GrGLfloat v0, GrGLfloat v1) {}
444GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform2i(GrGLint location, GrGLint v0, GrGLint v1) {}
445GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform2fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
446GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform2iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
447GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform3f(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2) {}
448GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform3i(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2) {}
449GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform3fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
450GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform3iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
451GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform4f(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2, GrGLfloat v3) {}
452GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform4i(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2, GrGLint v3) {}
453GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform4fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
454GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniform4iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
455GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniformMatrix2fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
456GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniformMatrix3fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
457GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniformMatrix4fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
458
459GrGLvoid GR_GL_FUNCTION_TYPE debugGLUseProgram(GrGLuint programID) {
460
461 GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
462 GrAlwaysAssert(program);
463
464 program->setInUse();
465}
466GrGLvoid GR_GL_FUNCTION_TYPE debugGLVertexAttrib4fv(GrGLuint indx, const GrGLfloat* values) {}
467GrGLvoid GR_GL_FUNCTION_TYPE debugGLVertexAttribPointer(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr) {}
468GrGLvoid GR_GL_FUNCTION_TYPE debugGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
469GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {}
470GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {}
471GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {}
472GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {}
473GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
474GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
475GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetFramebufferAttachmentParameteriv(GrGLenum target, GrGLenum attachment, GrGLenum pname, GrGLint* params) {}
476GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetRenderbufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {}
477GrGLvoid GR_GL_FUNCTION_TYPE debugGLRenderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
478GrGLvoid GR_GL_FUNCTION_TYPE debugGLRenderbufferStorageMultisample(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
479GrGLvoid GR_GL_FUNCTION_TYPE debugGLBlitFramebuffer(GrGLint srcX0, GrGLint srcY0, GrGLint srcX1, GrGLint srcY1, GrGLint dstX0, GrGLint dstY0, GrGLint dstX1, GrGLint dstY1, GrGLbitfield mask, GrGLenum filter) {}
480GrGLvoid GR_GL_FUNCTION_TYPE debugGLResolveMultisampleFramebuffer() {}
481GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFragDataLocationIndexed(GrGLuint program, GrGLuint colorNumber, GrGLuint index, const GrGLchar * name) {}
482
483GrGLenum GR_GL_FUNCTION_TYPE debugGLCheckFramebufferStatus(GrGLenum target) {
484 return GR_GL_FRAMEBUFFER_COMPLETE;
485}
486
487GrGLuint GR_GL_FUNCTION_TYPE debugGLCreateProgram() {
488
489 GrProgramObj *program = GrDebugGL::getInstance()->createProgram();
490
491 return program->getID();
492}
493
494GrGLuint GR_GL_FUNCTION_TYPE debugGLCreateShader(GrGLenum type) {
495
496 GrAlwaysAssert(GR_GL_VERTEX_SHADER == type || GR_GL_FRAGMENT_SHADER == type);
497
498 GrShaderObj *shader = GrDebugGL::getInstance()->createShader(type);
499
500 return shader->getID();
501}
502
503GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteProgram(GrGLuint programID) {
504
505 GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
506 GrAlwaysAssert(program);
507
508 program->unref();
509
510 if (program->getRefCount()) {
511 // someone is still using this program so we can't delete it here
512 program->setMarkedForDeletion();
513 } else {
514 program->deleteAction();
515 }
516}
517
518GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteShader(GrGLuint shaderID) {
519
520 GrShaderObj *shader = GrDebugGL::getInstance()->findShader(shaderID);
521 GrAlwaysAssert(shader);
522
523 shader->unref();
524
525 if (shader->getRefCount()) {
526 // someone is still using this shader so we can't delete it here
527 shader->setMarkedForDeletion();
528 } else {
529 shader->deleteAction();
530 }
531}
532
533// same function used for all glGen*(GLsize i, GLuint*) functions
534GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenIds(GrGLsizei n, GrGLuint* ids) {
535 static int gCurrID = 1;
536 for (int i = 0; i < n; ++i) {
537 ids[i] = ++gCurrID;
538 }
539}
540
541GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
542
543 for (int i = 0; i < n; ++i) {
544 GrBufferObj *buffer = GrDebugGL::getInstance()->createBuffer();
545 GrAlwaysAssert(buffer);
546 ids[i] = buffer->getID();
547 }
548}
549
550// same delete function for all glDelete*(GLsize i, const GLuint*) except buffers
551GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteIds(GrGLsizei n, const GrGLuint* ids) {}
552
553
554GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindBuffer(GrGLenum target, GrGLuint bufferID) {
555
556 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
557
558 GrBufferObj *buffer = GrDebugGL::getInstance()->findBuffer(bufferID);
559 // 0 is a permissable bufferID - it unbinds the current buffer
560
561 switch (target) {
562 case GR_GL_ARRAY_BUFFER:
563 if (GrDebugGL::getInstance()->getArrayBuffer()) {
564 // automatically break the binding of the old buffer
565 GrDebugGL::getInstance()->getArrayBuffer()->resetBound();
566 }
567 if (buffer) {
568 GrAlwaysAssert(!buffer->getBound());
569 }
570 GrDebugGL::getInstance()->setArrayBuffer(buffer);
571 if (buffer) {
572 buffer->setBound();
573 }
574 break;
575 case GR_GL_ELEMENT_ARRAY_BUFFER:
576 if (GrDebugGL::getInstance()->getElementArrayBuffer()) {
577 // automatically break the binding of the old buffer
578 GrDebugGL::getInstance()->getElementArrayBuffer()->resetBound();
579 }
580 if (buffer) {
581 GrAlwaysAssert(!buffer->getBound());
582 }
583 GrDebugGL::getInstance()->setElementArrayBuffer(buffer);
584 if (buffer) {
585 buffer->setBound();
586 }
587 break;
588 default:
589 GrCrash("Unexpected target to glBindBuffer");
590 break;
591 }
592}
593
594// deleting a bound buffer has the side effect of binding 0
595GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) {
596 // first potentially unbind the buffers
597 for (int i = 0; i < n; ++i) {
598
599 if (GrDebugGL::getInstance()->getArrayBuffer() &&
600 ids[i] == GrDebugGL::getInstance()->getArrayBuffer()->getID()) {
601 // this ID is the current array buffer
602 GrAlwaysAssert(GrDebugGL::getInstance()->getArrayBuffer()->getBound());
603 GrDebugGL::getInstance()->getArrayBuffer()->resetBound();
604 GrDebugGL::getInstance()->setArrayBuffer(NULL);
605 }
606 if (GrDebugGL::getInstance()->getElementArrayBuffer() &&
607 ids[i] == GrDebugGL::getInstance()->getElementArrayBuffer()->getID()) {
608 // this ID is the current element array buffer
609 GrAlwaysAssert(GrDebugGL::getInstance()->getElementArrayBuffer()->getBound());
610 GrDebugGL::getInstance()->getElementArrayBuffer()->resetBound();
611 GrDebugGL::getInstance()->setElementArrayBuffer(NULL);
612 }
613 }
614
615 // then actually "delete" the buffers
616 for (int i = 0; i < n; ++i) {
617 GrBufferObj *buffer = GrDebugGL::getInstance()->findBuffer(ids[i]);
618 GrAlwaysAssert(buffer);
619
620 GrAlwaysAssert(!buffer->getDeleted());
621 buffer->deleteAction();
622 }
623}
624
625// map a buffer to the caller's address space
626GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
627
628 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
629 GrAlwaysAssert(GR_GL_WRITE_ONLY == access); // GR_GL_READ_ONLY == access || || GR_GL_READ_WRIT == access);
630
631 GrBufferObj *buffer = NULL;
632 switch (target) {
633 case GR_GL_ARRAY_BUFFER:
634 buffer = GrDebugGL::getInstance()->getArrayBuffer();
635 break;
636 case GR_GL_ELEMENT_ARRAY_BUFFER:
637 buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
638 break;
639 default:
640 GrCrash("Unexpected target to glMapBuffer");
641 break;
642 }
643
644 if (buffer) {
645 GrAlwaysAssert(!buffer->getMapped());
646 buffer->setMapped();
647 return buffer->getDataPtr();
648 }
649
650 GrAlwaysAssert(false);
651 return NULL; // no buffer bound to the target
652}
653
654// remove a buffer from the caller's address space
655// TODO: check if the "access" method from "glMapBuffer" was honored
656GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
657
658 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
659
660 GrBufferObj *buffer = NULL;
661 switch (target) {
662 case GR_GL_ARRAY_BUFFER:
663 buffer = GrDebugGL::getInstance()->getArrayBuffer();
664 break;
665 case GR_GL_ELEMENT_ARRAY_BUFFER:
666 buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
667 break;
668 default:
669 GrCrash("Unexpected target to glUnmapBuffer");
670 break;
671 }
672
673 if (buffer) {
674 GrAlwaysAssert(buffer->getMapped());
675 buffer->resetMapped();
676 return GR_GL_TRUE;
677 }
678
679 GrAlwaysAssert(false);
680 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
681}
682
683GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target, GrGLenum value, GrGLint* params) {
684
685 GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
686 GrAlwaysAssert(GR_GL_BUFFER_SIZE == value || GR_GL_BUFFER_USAGE == value);
687
688 GrBufferObj *buffer = NULL;
689 switch (target) {
690 case GR_GL_ARRAY_BUFFER:
691 buffer = GrDebugGL::getInstance()->getArrayBuffer();
692 break;
693 case GR_GL_ELEMENT_ARRAY_BUFFER:
694 buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
695 break;
696 }
697
698 GrAlwaysAssert(buffer);
699
700 switch (value) {
701 case GR_GL_BUFFER_MAPPED:
702 *params = GR_GL_FALSE;
703 if (buffer)
704 *params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
705 break;
706 case GR_GL_BUFFER_SIZE:
707 *params = 0;
708 if (buffer)
709 *params = buffer->getSize();
710 break;
711 case GR_GL_BUFFER_USAGE:
712 *params = GR_GL_STATIC_DRAW;
713 if (buffer)
714 *params = buffer->getUsage();
715 break;
716 default:
717 GrCrash("Unexpected value to glGetBufferParamateriv");
718 break;
719 }
720};
721
722GrGLenum GR_GL_FUNCTION_TYPE debugGLGetError() {
723 return GR_GL_NO_ERROR;
724}
725
726GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetIntegerv(GrGLenum pname, GrGLint* params) {
727 // TODO: remove from Ganesh the #defines for gets we don't use.
728 // We would like to minimize gets overall due to performance issues
729 switch (pname) {
730 case GR_GL_STENCIL_BITS:
731 *params = 8;
732 break;
733 case GR_GL_SAMPLES:
734 *params = 1;
735 break;
736 case GR_GL_FRAMEBUFFER_BINDING:
737 *params = 0;
738 break;
739 case GR_GL_VIEWPORT:
740 params[0] = 0;
741 params[1] = 0;
742 params[2] = 800;
743 params[3] = 600;
744 break;
745 case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
746 *params = 8;
747 break;
748 case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
749 *params = 16;
750 break;
751 case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
752 *params = 16 * 4;
753 break;
754 case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
755 *params = 0;
756 break;
757 case GR_GL_COMPRESSED_TEXTURE_FORMATS:
758 break;
759 case GR_GL_MAX_TEXTURE_SIZE:
760 *params = 8192;
761 break;
762 case GR_GL_MAX_RENDERBUFFER_SIZE:
763 *params = 8192;
764 break;
765 case GR_GL_MAX_SAMPLES:
766 *params = 32;
767 break;
768 case GR_GL_MAX_VERTEX_ATTRIBS:
769 *params = 16;
770 break;
771 case GR_GL_MAX_TEXTURE_UNITS:
772 *params = GrDebugGL::getInstance()->getMaxTextureUnits();
773 break;
774 default:
775 GrCrash("Unexpected pname to GetIntegerv");
776 }
777}
778// used for both the program and shader info logs
779GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, char* infolog) {
780 if (length) {
781 *length = 0;
782 }
783 if (bufsize > 0) {
784 *infolog = 0;
785 }
786}
787
788// used for both the program and shader params
789GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetShaderOrProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) {
790 switch (pname) {
791 case GR_GL_LINK_STATUS: // fallthru
792 case GR_GL_COMPILE_STATUS:
793 *params = GR_GL_TRUE;
794 break;
795 case GR_GL_INFO_LOG_LENGTH:
796 *params = 0;
797 break;
798 // we don't expect any other pnames
799 default:
800 GrCrash("Unexpected pname to GetProgramiv");
801 break;
802 }
803}
804
805namespace {
806template <typename T>
807void query_result(GrGLenum GLtarget, GrGLenum pname, T *params) {
808 switch (pname) {
809 case GR_GL_QUERY_RESULT_AVAILABLE:
810 *params = GR_GL_TRUE;
811 break;
812 case GR_GL_QUERY_RESULT:
813 *params = 0;
814 break;
815 default:
816 GrCrash("Unexpected pname passed to GetQueryObject.");
817 break;
818 }
819}
820}
821
822// Queries on the null GL just don't do anything at all. We could potentially make
823// the timers work.
824GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) {
825 switch (pname) {
826 case GR_GL_CURRENT_QUERY:
827 *params = 0;
828 break;
829 case GR_GL_QUERY_COUNTER_BITS:
830 *params = 32;
831 break;
832 default:
833 GrCrash("Unexpected pname passed GetQueryiv.");
834 }
835}
836GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) {
837 query_result(id, pname, params);
838}
839GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) {
840 query_result(id, pname, params);
841}
842GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) {
843 query_result(id, pname, params);
844}
845GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) {
846 query_result(id, pname, params);
847}
848
849const GrGLubyte* GR_GL_FUNCTION_TYPE debugGLGetString(GrGLenum name) {
850 switch (name) {
851 case GR_GL_EXTENSIONS:
852 return (const GrGLubyte*)"GL_ARB_framebuffer_object GL_ARB_blend_func_extended GL_ARB_timer_query GL_ARB_draw_buffers GL_ARB_occlusion_query GL_EXT_blend_color GL_EXT_stencil_wrap";
853 case GR_GL_VERSION:
854 return (const GrGLubyte*)"4.0 Null GL";
855 case GR_GL_SHADING_LANGUAGE_VERSION:
856 return (const GrGLubyte*)"4.20.8 Null GLSL";
857 default:
858 GrCrash("Unexpected name to GetString");
859 return NULL;
860 }
861}
862
863// we used to use this to query stuff about externally created textures, now we just
864// require clients to tell us everything about the texture.
865GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetTexLevelParameteriv(GrGLenum target, GrGLint level, GrGLenum pname, GrGLint* params) {
866 GrCrash("Should never query texture parameters.");
867}
868
869GrGLint GR_GL_FUNCTION_TYPE debugGLGetUniformLocation(GrGLuint program, const char* name) {
870 static int gUniLocation = 0;
871 return ++gUniLocation;
872}
873
874const GrGLInterface* GrGLCreateDebugInterface() {
875 // The gl functions are not context-specific so we create one global
876 // interface
877 static SkAutoTUnref<GrGLInterface> glInterface;
878 if (!glInterface.get()) {
879 GrGLInterface* interface = new GrGLInterface;
880 glInterface.reset(interface);
881 interface->fBindingsExported = kDesktop_GrGLBinding;
882 interface->fActiveTexture = debugGLActiveTexture;
883 interface->fAttachShader = debugGLAttachShader;
884 interface->fBeginQuery = debugGLBeginQuery;
885 interface->fBindAttribLocation = debugGLBindAttribLocation;
886 interface->fBindBuffer = debugGLBindBuffer;
887 interface->fBindFragDataLocation = debugGLBindFragDataLocation;
888 interface->fBindTexture = debugGLBindTexture;
889 interface->fBlendColor = debugGLBlendColor;
890 interface->fBlendFunc = debugGLBlendFunc;
891 interface->fBufferData = debugGLBufferData;
892 interface->fBufferSubData = debugGLBufferSubData;
893 interface->fClear = debugGLClear;
894 interface->fClearColor = debugGLClearColor;
895 interface->fClearStencil = debugGLClearStencil;
896 interface->fColorMask = debugGLColorMask;
897 interface->fCompileShader = debugGLCompileShader;
898 interface->fCompressedTexImage2D = debugGLCompressedTexImage2D;
899 interface->fCreateProgram = debugGLCreateProgram;
900 interface->fCreateShader = debugGLCreateShader;
901 interface->fCullFace = debugGLCullFace;
902 interface->fDeleteBuffers = debugGLDeleteBuffers;
903 interface->fDeleteProgram = debugGLDeleteProgram;
904 interface->fDeleteQueries = debugGLDeleteIds;
905 interface->fDeleteShader = debugGLDeleteShader;
906 interface->fDeleteTextures = debugGLDeleteIds;
907 interface->fDepthMask = debugGLDepthMask;
908 interface->fDisable = debugGLDisable;
909 interface->fDisableVertexAttribArray = debugGLDisableVertexAttribArray;
910 interface->fDrawArrays = debugGLDrawArrays;
911 interface->fDrawBuffer = debugGLDrawBuffer;
912 interface->fDrawBuffers = debugGLDrawBuffers;
913 interface->fDrawElements = debugGLDrawElements;
914 interface->fEnable = debugGLEnable;
915 interface->fEnableVertexAttribArray = debugGLEnableVertexAttribArray;
916 interface->fEndQuery = debugGLEndQuery;
917 interface->fFinish = debugGLFinish;
918 interface->fFlush = debugGLFlush;
919 interface->fFrontFace = debugGLFrontFace;
920 interface->fGenBuffers = debugGLGenBuffers;
921 interface->fGenQueries = debugGLGenIds;
922 interface->fGenTextures = debugGLGenIds;
923 interface->fGetBufferParameteriv = debugGLGetBufferParameteriv;
924 interface->fGetError = debugGLGetError;
925 interface->fGetIntegerv = debugGLGetIntegerv;
926 interface->fGetQueryObjecti64v = debugGLGetQueryObjecti64v;
927 interface->fGetQueryObjectiv = debugGLGetQueryObjectiv;
928 interface->fGetQueryObjectui64v = debugGLGetQueryObjectui64v;
929 interface->fGetQueryObjectuiv = debugGLGetQueryObjectuiv;
930 interface->fGetQueryiv = debugGLGetQueryiv;
931 interface->fGetProgramInfoLog = debugGLGetInfoLog;
932 interface->fGetProgramiv = debugGLGetShaderOrProgramiv;
933 interface->fGetShaderInfoLog = debugGLGetInfoLog;
934 interface->fGetShaderiv = debugGLGetShaderOrProgramiv;
935 interface->fGetString = debugGLGetString;
936 interface->fGetTexLevelParameteriv = debugGLGetTexLevelParameteriv;
937 interface->fGetUniformLocation = debugGLGetUniformLocation;
938 interface->fLineWidth = debugGLLineWidth;
939 interface->fLinkProgram = debugGLLinkProgram;
940 interface->fPixelStorei = debugGLPixelStorei;
941 interface->fQueryCounter = debugGLQueryCounter;
942 interface->fReadBuffer = debugGLReadBuffer;
943 interface->fReadPixels = debugGLReadPixels;
944 interface->fScissor = debugGLScissor;
945 interface->fShaderSource = debugGLShaderSource;
946 interface->fStencilFunc = debugGLStencilFunc;
947 interface->fStencilFuncSeparate = debugGLStencilFuncSeparate;
948 interface->fStencilMask = debugGLStencilMask;
949 interface->fStencilMaskSeparate = debugGLStencilMaskSeparate;
950 interface->fStencilOp = debugGLStencilOp;
951 interface->fStencilOpSeparate = debugGLStencilOpSeparate;
952 interface->fTexImage2D = debugGLTexImage2D;
953 interface->fTexParameteri = debugGLTexParameteri;
954 interface->fTexSubImage2D = debugGLTexSubImage2D;
955 interface->fTexStorage2D = debugGLTexStorage2D;
956 interface->fUniform1f = debugGLUniform1f;
957 interface->fUniform1i = debugGLUniform1i;
958 interface->fUniform1fv = debugGLUniform1fv;
959 interface->fUniform1iv = debugGLUniform1iv;
960 interface->fUniform2f = debugGLUniform2f;
961 interface->fUniform2i = debugGLUniform2i;
962 interface->fUniform2fv = debugGLUniform2fv;
963 interface->fUniform2iv = debugGLUniform2iv;
964 interface->fUniform3f = debugGLUniform3f;
965 interface->fUniform3i = debugGLUniform3i;
966 interface->fUniform3fv = debugGLUniform3fv;
967 interface->fUniform3iv = debugGLUniform3iv;
968 interface->fUniform4f = debugGLUniform4f;
969 interface->fUniform4i = debugGLUniform4i;
970 interface->fUniform4fv = debugGLUniform4fv;
971 interface->fUniform4iv = debugGLUniform4iv;
972 interface->fUniformMatrix2fv = debugGLUniformMatrix2fv;
973 interface->fUniformMatrix3fv = debugGLUniformMatrix3fv;
974 interface->fUniformMatrix4fv = debugGLUniformMatrix4fv;
975 interface->fUseProgram = debugGLUseProgram;
976 interface->fVertexAttrib4fv = debugGLVertexAttrib4fv;
977 interface->fVertexAttribPointer = debugGLVertexAttribPointer;
978 interface->fViewport = debugGLViewport;
979 interface->fBindFramebuffer = debugGLBindFramebuffer;
980 interface->fBindRenderbuffer = debugGLBindRenderbuffer;
981 interface->fCheckFramebufferStatus = debugGLCheckFramebufferStatus;
982 interface->fDeleteFramebuffers = debugGLDeleteFramebuffers;
983 interface->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
984 interface->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
985 interface->fFramebufferTexture2D = debugGLFramebufferTexture2D;
986 interface->fGenFramebuffers = debugGLGenIds;
987 interface->fGenRenderbuffers = debugGLGenIds;
988 interface->fGetFramebufferAttachmentParameteriv = debugGLGetFramebufferAttachmentParameteriv;
989 interface->fGetRenderbufferParameteriv = debugGLGetRenderbufferParameteriv;
990 interface->fRenderbufferStorage = debugGLRenderbufferStorage;
991 interface->fRenderbufferStorageMultisample = debugGLRenderbufferStorageMultisample;
992 interface->fBlitFramebuffer = debugGLBlitFramebuffer;
993 interface->fResolveMultisampleFramebuffer = debugGLResolveMultisampleFramebuffer;
994 interface->fMapBuffer = debugGLMapBuffer;
995 interface->fUnmapBuffer = debugGLUnmapBuffer;
996 interface->fBindFragDataLocationIndexed = debugGLBindFragDataLocationIndexed;
997 }
998 glInterface.get()->ref();
999 return glInterface.get();
1000}