1 /*
2 * Copyright 2011 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
8
9 #include "gl/GrGLInterface.h"
10 #include "GrGLDefines.h"
11 #include "SkTDArray.h"
12 #include "GrGLNoOpInterface.h"
13
14 // Functions not declared in GrGLBogusInterface.h (not common with the Debug GL interface).
15
16 namespace { // added to suppress 'no previous prototype' warning
17
18 class GrBufferObj {
19 public:
GrBufferObj(GrGLuint id)20 GrBufferObj(GrGLuint id) : fID(id), fDataPtr(NULL), fSize(0), fMapped(false) {
21 }
~GrBufferObj()22 ~GrBufferObj() { SkDELETE_ARRAY(fDataPtr); }
23
allocate(GrGLsizeiptr size,const GrGLchar * dataPtr)24 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
25 if (NULL != fDataPtr) {
26 SkASSERT(0 != fSize);
27 SkDELETE_ARRAY(fDataPtr);
28 }
29
30 fSize = size;
31 fDataPtr = SkNEW_ARRAY(char, size);
32 }
33
id() const34 GrGLuint id() const { return fID; }
dataPtr()35 GrGLchar* dataPtr() { return fDataPtr; }
size() const36 GrGLsizeiptr size() const { return fSize; }
37
setMapped(bool mapped)38 void setMapped(bool mapped) { fMapped = mapped; }
mapped() const39 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 // In debug builds we do asserts that ensure we agree with GL about when a buffer
49 // is mapped.
50 static SkTDArray<GrBufferObj*> gBuffers; // slot 0 is reserved for head of free list
51 static GrGLuint gCurrArrayBuffer;
52 static GrGLuint gCurrElementArrayBuffer;
53
look_up(GrGLuint id)54 static GrBufferObj* look_up(GrGLuint id) {
55 GrBufferObj* buffer = gBuffers[id];
56 SkASSERT(NULL != buffer && buffer->id() == id);
57 return buffer;
58 }
59
create_buffer()60 static GrBufferObj* create_buffer() {
61 if (0 == gBuffers.count()) {
62 // slot zero is reserved for the head of the free list
63 *gBuffers.append() = NULL;
64 }
65
66 GrGLuint id;
67 GrBufferObj* buffer;
68
69 if (NULL == gBuffers[0]) {
70 // no free slots - create a new one
71 id = gBuffers.count();
72 buffer = SkNEW_ARGS(GrBufferObj, (id));
73 gBuffers.append(1, &buffer);
74 } else {
75 // recycle a slot from the free list
76 id = SkTCast<GrGLuint>(gBuffers[0]);
77 gBuffers[0] = gBuffers[id];
78
79 buffer = SkNEW_ARGS(GrBufferObj, (id));
80 gBuffers[id] = buffer;
81 }
82
83 return buffer;
84 }
85
delete_buffer(GrBufferObj * buffer)86 static void delete_buffer(GrBufferObj* buffer) {
87 SkASSERT(gBuffers.count() > 0);
88
89 GrGLuint id = buffer->id();
90 SkDELETE(buffer);
91
92 // Add this slot to the free list
93 gBuffers[id] = gBuffers[0];
94 gBuffers[0] = SkTCast<GrBufferObj*>((const void*)(intptr_t)id);
95 }
96
nullGLActiveTexture(GrGLenum texture)97 GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {}
nullGLAttachShader(GrGLuint program,GrGLuint shader)98 GrGLvoid GR_GL_FUNCTION_TYPE nullGLAttachShader(GrGLuint program, GrGLuint shader) {}
nullGLBeginQuery(GrGLenum target,GrGLuint id)99 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBeginQuery(GrGLenum target, GrGLuint id) {}
nullGLBindAttribLocation(GrGLuint program,GrGLuint index,const char * name)100 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {}
nullGLBindTexture(GrGLenum target,GrGLuint texture)101 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindTexture(GrGLenum target, GrGLuint texture) {}
nullGLBindVertexArray(GrGLuint id)102 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindVertexArray(GrGLuint id) {}
103
nullGLGenBuffers(GrGLsizei n,GrGLuint * ids)104 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
105
106 for (int i = 0; i < n; ++i) {
107 GrBufferObj* buffer = create_buffer();
108 ids[i] = buffer->id();
109 }
110 }
111
nullGLGenerateMipmap(GrGLenum target)112 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenerateMipmap(GrGLenum target) {}
113
nullGLBufferData(GrGLenum target,GrGLsizeiptr size,const GrGLvoid * data,GrGLenum usage)114 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBufferData(GrGLenum target,
115 GrGLsizeiptr size,
116 const GrGLvoid* data,
117 GrGLenum usage) {
118 GrGLuint id = 0;
119
120 switch (target) {
121 case GR_GL_ARRAY_BUFFER:
122 id = gCurrArrayBuffer;
123 break;
124 case GR_GL_ELEMENT_ARRAY_BUFFER:
125 id = gCurrElementArrayBuffer;
126 break;
127 default:
128 SkFAIL("Unexpected target to nullGLBufferData");
129 break;
130 }
131
132 if (id > 0) {
133 GrBufferObj* buffer = look_up(id);
134 buffer->allocate(size, (const GrGLchar*) data);
135 }
136 }
137
nullGLPixelStorei(GrGLenum pname,GrGLint param)138 GrGLvoid GR_GL_FUNCTION_TYPE nullGLPixelStorei(GrGLenum pname, GrGLint param) {}
nullGLReadPixels(GrGLint x,GrGLint y,GrGLsizei width,GrGLsizei height,GrGLenum format,GrGLenum type,GrGLvoid * pixels)139 GrGLvoid GR_GL_FUNCTION_TYPE nullGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {}
nullGLUseProgram(GrGLuint program)140 GrGLvoid GR_GL_FUNCTION_TYPE nullGLUseProgram(GrGLuint program) {}
nullGLViewport(GrGLint x,GrGLint y,GrGLsizei width,GrGLsizei height)141 GrGLvoid GR_GL_FUNCTION_TYPE nullGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
nullGLBindFramebuffer(GrGLenum target,GrGLuint framebuffer)142 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {}
nullGLBindRenderbuffer(GrGLenum target,GrGLuint renderbuffer)143 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {}
nullGLDeleteFramebuffers(GrGLsizei n,const GrGLuint * framebuffers)144 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {}
nullGLDeleteRenderbuffers(GrGLsizei n,const GrGLuint * renderbuffers)145 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {}
nullGLFramebufferRenderbuffer(GrGLenum target,GrGLenum attachment,GrGLenum renderbuffertarget,GrGLuint renderbuffer)146 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
nullGLFramebufferTexture2D(GrGLenum target,GrGLenum attachment,GrGLenum textarget,GrGLuint texture,GrGLint level)147 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
148
nullGLCreateProgram()149 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateProgram() {
150 static GrGLuint gCurrID = 0;
151 return ++gCurrID;
152 }
153
nullGLCreateShader(GrGLenum type)154 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateShader(GrGLenum type) {
155 static GrGLuint gCurrID = 0;
156 return ++gCurrID;
157 }
158
159 // same delete used for shaders and programs
nullGLDelete(GrGLuint program)160 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDelete(GrGLuint program) {
161 }
162
nullGLBindBuffer(GrGLenum target,GrGLuint buffer)163 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindBuffer(GrGLenum target, GrGLuint buffer) {
164 switch (target) {
165 case GR_GL_ARRAY_BUFFER:
166 gCurrArrayBuffer = buffer;
167 break;
168 case GR_GL_ELEMENT_ARRAY_BUFFER:
169 gCurrElementArrayBuffer = buffer;
170 break;
171 }
172 }
173
174 // deleting a bound buffer has the side effect of binding 0
nullGLDeleteBuffers(GrGLsizei n,const GrGLuint * ids)175 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) {
176 for (int i = 0; i < n; ++i) {
177 if (ids[i] == gCurrArrayBuffer) {
178 gCurrArrayBuffer = 0;
179 }
180 if (ids[i] == gCurrElementArrayBuffer) {
181 gCurrElementArrayBuffer = 0;
182 }
183
184 GrBufferObj* buffer = look_up(ids[i]);
185 delete_buffer(buffer);
186 }
187 }
188
nullGLMapBufferRange(GrGLenum target,GrGLintptr offset,GrGLsizeiptr length,GrGLbitfield access)189 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBufferRange(GrGLenum target, GrGLintptr offset,
190 GrGLsizeiptr length, GrGLbitfield access) {
191 GrGLuint id = 0;
192 switch (target) {
193 case GR_GL_ARRAY_BUFFER:
194 id = gCurrArrayBuffer;
195 break;
196 case GR_GL_ELEMENT_ARRAY_BUFFER:
197 id = gCurrElementArrayBuffer;
198 break;
199 }
200
201 if (id > 0) {
202 // We just ignore the offset and length here.
203 GrBufferObj* buffer = look_up(id);
204 SkASSERT(!buffer->mapped());
205 buffer->setMapped(true);
206 return buffer->dataPtr();
207 }
208 return NULL;
209 }
210
nullGLMapBuffer(GrGLenum target,GrGLenum access)211 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
212 GrGLuint id = 0;
213 switch (target) {
214 case GR_GL_ARRAY_BUFFER:
215 id = gCurrArrayBuffer;
216 break;
217 case GR_GL_ELEMENT_ARRAY_BUFFER:
218 id = gCurrElementArrayBuffer;
219 break;
220 }
221
222 if (id > 0) {
223 GrBufferObj* buffer = look_up(id);
224 SkASSERT(!buffer->mapped());
225 buffer->setMapped(true);
226 return buffer->dataPtr();
227 }
228
229 SkASSERT(false);
230 return NULL; // no buffer bound to target
231 }
232
nullGLFlushMappedBufferRange(GrGLenum target,GrGLintptr offset,GrGLsizeiptr length)233 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFlushMappedBufferRange(GrGLenum target,
234 GrGLintptr offset,
235 GrGLsizeiptr length) {}
236
237
nullGLUnmapBuffer(GrGLenum target)238 GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) {
239 GrGLuint id = 0;
240 switch (target) {
241 case GR_GL_ARRAY_BUFFER:
242 id = gCurrArrayBuffer;
243 break;
244 case GR_GL_ELEMENT_ARRAY_BUFFER:
245 id = gCurrElementArrayBuffer;
246 break;
247 }
248 if (id > 0) {
249 GrBufferObj* buffer = look_up(id);
250 SkASSERT(buffer->mapped());
251 buffer->setMapped(false);
252 return GR_GL_TRUE;
253 }
254
255 GrAlwaysAssert(false);
256 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
257 }
258
nullGLGetBufferParameteriv(GrGLenum target,GrGLenum pname,GrGLint * params)259 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {
260 switch (pname) {
261 case GR_GL_BUFFER_MAPPED: {
262 *params = GR_GL_FALSE;
263 GrGLuint id = 0;
264 switch (target) {
265 case GR_GL_ARRAY_BUFFER:
266 id = gCurrArrayBuffer;
267 break;
268 case GR_GL_ELEMENT_ARRAY_BUFFER:
269 id = gCurrElementArrayBuffer;
270 break;
271 }
272 if (id > 0) {
273 GrBufferObj* buffer = look_up(id);
274 if (buffer->mapped()) {
275 *params = GR_GL_TRUE;
276 }
277 }
278 break; }
279 default:
280 SkFAIL("Unexpected pname to GetBufferParamateriv");
281 break;
282 }
283 };
284
285 } // end anonymous namespace
286
GrGLCreateNullInterface()287 const GrGLInterface* GrGLCreateNullInterface() {
288 GrGLInterface* interface = SkNEW(GrGLInterface);
289
290 interface->fStandard = kGL_GrGLStandard;
291
292 GrGLInterface::Functions* functions = &interface->fFunctions;
293 functions->fActiveTexture = nullGLActiveTexture;
294 functions->fAttachShader = nullGLAttachShader;
295 functions->fBeginQuery = nullGLBeginQuery;
296 functions->fBindAttribLocation = nullGLBindAttribLocation;
297 functions->fBindBuffer = nullGLBindBuffer;
298 functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
299 functions->fBindTexture = nullGLBindTexture;
300 functions->fBindVertexArray = nullGLBindVertexArray;
301 functions->fBlendColor = noOpGLBlendColor;
302 functions->fBlendFunc = noOpGLBlendFunc;
303 functions->fBufferData = nullGLBufferData;
304 functions->fBufferSubData = noOpGLBufferSubData;
305 functions->fClear = noOpGLClear;
306 functions->fClearColor = noOpGLClearColor;
307 functions->fClearStencil = noOpGLClearStencil;
308 functions->fColorMask = noOpGLColorMask;
309 functions->fCompileShader = noOpGLCompileShader;
310 functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
311 functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
312 functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
313 functions->fCreateProgram = nullGLCreateProgram;
314 functions->fCreateShader = nullGLCreateShader;
315 functions->fCullFace = noOpGLCullFace;
316 functions->fDeleteBuffers = nullGLDeleteBuffers;
317 functions->fDeleteProgram = nullGLDelete;
318 functions->fDeleteQueries = noOpGLDeleteIds;
319 functions->fDeleteShader = nullGLDelete;
320 functions->fDeleteTextures = noOpGLDeleteIds;
321 functions->fDeleteVertexArrays = noOpGLDeleteIds;
322 functions->fDepthMask = noOpGLDepthMask;
323 functions->fDisable = noOpGLDisable;
324 functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
325 functions->fDrawArrays = noOpGLDrawArrays;
326 functions->fDrawBuffer = noOpGLDrawBuffer;
327 functions->fDrawBuffers = noOpGLDrawBuffers;
328 functions->fDrawElements = noOpGLDrawElements;
329 functions->fEnable = noOpGLEnable;
330 functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
331 functions->fEndQuery = noOpGLEndQuery;
332 functions->fFinish = noOpGLFinish;
333 functions->fFlush = noOpGLFlush;
334 functions->fFlushMappedBufferRange = nullGLFlushMappedBufferRange;
335 functions->fFrontFace = noOpGLFrontFace;
336 functions->fGenBuffers = nullGLGenBuffers;
337 functions->fGenerateMipmap = nullGLGenerateMipmap;
338 functions->fGenQueries = noOpGLGenIds;
339 functions->fGenTextures = noOpGLGenIds;
340 functions->fGenVertexArrays = noOpGLGenIds;
341 functions->fGetBufferParameteriv = nullGLGetBufferParameteriv;
342 functions->fGetError = noOpGLGetError;
343 functions->fGetIntegerv = noOpGLGetIntegerv;
344 functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
345 functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
346 functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
347 functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
348 functions->fGetQueryiv = noOpGLGetQueryiv;
349 functions->fGetProgramInfoLog = noOpGLGetInfoLog;
350 functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
351 functions->fGetShaderInfoLog = noOpGLGetInfoLog;
352 functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
353 functions->fGetString = noOpGLGetString;
354 functions->fGetStringi = noOpGLGetStringi;
355 functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
356 functions->fGetUniformLocation = noOpGLGetUniformLocation;
357 functions->fInsertEventMarker = noOpGLInsertEventMarker;
358 functions->fLineWidth = noOpGLLineWidth;
359 functions->fLinkProgram = noOpGLLinkProgram;
360 functions->fMapBuffer = nullGLMapBuffer;
361 functions->fMapBufferRange = nullGLMapBufferRange;
362 functions->fPixelStorei = nullGLPixelStorei;
363 functions->fPopGroupMarker = noOpGLPopGroupMarker;
364 functions->fPushGroupMarker = noOpGLPushGroupMarker;
365 functions->fQueryCounter = noOpGLQueryCounter;
366 functions->fReadBuffer = noOpGLReadBuffer;
367 functions->fReadPixels = nullGLReadPixels;
368 functions->fScissor = noOpGLScissor;
369 functions->fShaderSource = noOpGLShaderSource;
370 functions->fStencilFunc = noOpGLStencilFunc;
371 functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
372 functions->fStencilMask = noOpGLStencilMask;
373 functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
374 functions->fStencilOp = noOpGLStencilOp;
375 functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
376 functions->fTexImage2D = noOpGLTexImage2D;
377 functions->fTexParameteri = noOpGLTexParameteri;
378 functions->fTexParameteriv = noOpGLTexParameteriv;
379 functions->fTexSubImage2D = noOpGLTexSubImage2D;
380 functions->fTexStorage2D = noOpGLTexStorage2D;
381 functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
382 functions->fUniform1f = noOpGLUniform1f;
383 functions->fUniform1i = noOpGLUniform1i;
384 functions->fUniform1fv = noOpGLUniform1fv;
385 functions->fUniform1iv = noOpGLUniform1iv;
386 functions->fUniform2f = noOpGLUniform2f;
387 functions->fUniform2i = noOpGLUniform2i;
388 functions->fUniform2fv = noOpGLUniform2fv;
389 functions->fUniform2iv = noOpGLUniform2iv;
390 functions->fUniform3f = noOpGLUniform3f;
391 functions->fUniform3i = noOpGLUniform3i;
392 functions->fUniform3fv = noOpGLUniform3fv;
393 functions->fUniform3iv = noOpGLUniform3iv;
394 functions->fUniform4f = noOpGLUniform4f;
395 functions->fUniform4i = noOpGLUniform4i;
396 functions->fUniform4fv = noOpGLUniform4fv;
397 functions->fUniform4iv = noOpGLUniform4iv;
398 functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
399 functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
400 functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
401 functions->fUnmapBuffer = nullGLUnmapBuffer;
402 functions->fUseProgram = nullGLUseProgram;
403 functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
404 functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
405 functions->fViewport = nullGLViewport;
406 functions->fBindFramebuffer = nullGLBindFramebuffer;
407 functions->fBindRenderbuffer = nullGLBindRenderbuffer;
408 functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
409 functions->fDeleteFramebuffers = nullGLDeleteFramebuffers;
410 functions->fDeleteRenderbuffers = nullGLDeleteRenderbuffers;
411 functions->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer;
412 functions->fFramebufferTexture2D = nullGLFramebufferTexture2D;
413 functions->fGenFramebuffers = noOpGLGenIds;
414 functions->fGenRenderbuffers = noOpGLGenIds;
415 functions->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv;
416 functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
417 functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
418 functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample;
419 functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
420 functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer;
421 functions->fMatrixLoadf = noOpGLMatrixLoadf;
422 functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
423 functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed;
424
425 interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
426 functions->fGetIntegerv);
427 return interface;
428 }
429