2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "gl/GrGLInterface.h"
10 #include "GrGLDefines.h"
11 #include "SkTDArray.h"
12 #include "GrGLNoOpInterface.h"
17 SK_DECLARE_INST_COUNT_ROOT(BufferObj);
19 BufferObj(GrGLuint id) : fID(id), fDataPtr(NULL), fSize(0), fMapped(false) {
21 ~BufferObj() { SkDELETE_ARRAY(fDataPtr); }
23 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
26 SkDELETE_ARRAY(fDataPtr);
30 fDataPtr = SkNEW_ARRAY(char, size);
33 GrGLuint id() const { return fID; }
34 GrGLchar* dataPtr() { return fDataPtr; }
35 GrGLsizeiptr size() const { return fSize; }
37 void setMapped(bool mapped) { fMapped = mapped; }
38 bool mapped() const { return fMapped; }
43 GrGLsizeiptr fSize; // size in bytes
47 // This class maintains a sparsely populated array of buffer pointers.
50 SK_DECLARE_INST_COUNT_ROOT(BufferManager);
52 BufferManager() : fFreeListHead(kFreeListEnd) {}
55 // NULL out the entries that are really free list links rather than ptrs before deleting.
56 intptr_t curr = fFreeListHead;
57 while (kFreeListEnd != curr) {
58 intptr_t next = reinterpret_cast<intptr_t>(fBuffers[SkToS32(curr)]);
59 fBuffers[SkToS32(curr)] = NULL;
66 BufferObj* lookUp(GrGLuint id) {
67 BufferObj* buffer = fBuffers[id];
68 SkASSERT(buffer && buffer->id() == id);
76 if (kFreeListEnd == fFreeListHead) {
77 // no free slots - create a new one
78 id = fBuffers.count();
79 buffer = SkNEW_ARGS(BufferObj, (id));
80 *fBuffers.append() = buffer;
82 // grab the head of the free list and advance the head to the next free slot.
83 id = static_cast<GrGLuint>(fFreeListHead);
84 fFreeListHead = reinterpret_cast<intptr_t>(fBuffers[id]);
86 buffer = SkNEW_ARGS(BufferObj, (id));
87 fBuffers[id] = buffer;
93 void free(BufferObj* buffer) {
94 SkASSERT(fBuffers.count() > 0);
96 GrGLuint id = buffer->id();
99 fBuffers[id] = reinterpret_cast<BufferObj*>(fFreeListHead);
104 static const intptr_t kFreeListEnd = -1;
105 // Index of the first entry of fBuffers in the free list. Free slots in fBuffers are indices to
106 // the next free slot. The last free slot has a value of kFreeListEnd.
107 intptr_t fFreeListHead;
108 SkTDArray<BufferObj*> fBuffers;
112 * The global-to-thread state object for the null interface. All null interfaces on the
113 * same thread currently share one of these. This means two null contexts on the same thread
114 * can interfere with each other. It may make sense to more integrate this into SkNullGLContext
115 * and use it's makeCurrent mechanism.
117 struct ThreadContext {
119 SK_DECLARE_INST_COUNT_ROOT(ThreadContext);
121 BufferManager fBufferManager;
122 GrGLuint fCurrArrayBuffer;
123 GrGLuint fCurrElementArrayBuffer;
124 GrGLuint fCurrProgramID;
125 GrGLuint fCurrShaderID;
127 static ThreadContext* Get() {
128 return reinterpret_cast<ThreadContext*>(SkTLS::Get(Create, Delete));
132 : fCurrArrayBuffer(0)
133 , fCurrElementArrayBuffer(0)
135 , fCurrShaderID(0) {}
138 static void* Create() { return SkNEW(ThreadContext ); }
139 static void Delete(void* context) { SkDELETE(reinterpret_cast<ThreadContext *>(context)); }
142 // Functions not declared in GrGLBogusInterface.h (not common with the Debug GL interface).
144 namespace { // added to suppress 'no previous prototype' warning
146 GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {}
147 GrGLvoid GR_GL_FUNCTION_TYPE nullGLAttachShader(GrGLuint program, GrGLuint shader) {}
148 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBeginQuery(GrGLenum target, GrGLuint id) {}
149 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {}
150 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindTexture(GrGLenum target, GrGLuint texture) {}
151 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindVertexArray(GrGLuint id) {}
153 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
154 ThreadContext* ctx = ThreadContext::Get();
155 for (int i = 0; i < n; ++i) {
156 BufferObj* buffer = ctx->fBufferManager.create();
157 ids[i] = buffer->id();
161 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenerateMipmap(GrGLenum target) {}
163 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBufferData(GrGLenum target,
165 const GrGLvoid* data,
167 ThreadContext* ctx = ThreadContext::Get();
171 case GR_GL_ARRAY_BUFFER:
172 id = ctx->fCurrArrayBuffer;
174 case GR_GL_ELEMENT_ARRAY_BUFFER:
175 id = ctx->fCurrElementArrayBuffer;
178 SkFAIL("Unexpected target to nullGLBufferData");
183 BufferObj* buffer = ctx->fBufferManager.lookUp(id);
184 buffer->allocate(size, (const GrGLchar*) data);
188 GrGLvoid GR_GL_FUNCTION_TYPE nullGLPixelStorei(GrGLenum pname, GrGLint param) {}
189 GrGLvoid GR_GL_FUNCTION_TYPE nullGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {}
190 GrGLvoid GR_GL_FUNCTION_TYPE nullGLUseProgram(GrGLuint program) {}
191 GrGLvoid GR_GL_FUNCTION_TYPE nullGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
192 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {}
193 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {}
194 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {}
195 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {}
196 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
197 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
199 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateProgram() {
200 return ++ThreadContext::Get()->fCurrProgramID;
203 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateShader(GrGLenum type) {
204 return ++ThreadContext::Get()->fCurrShaderID;
207 // same delete used for shaders and programs
208 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDelete(GrGLuint program) {
211 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindBuffer(GrGLenum target, GrGLuint buffer) {
212 ThreadContext* ctx = ThreadContext::Get();
214 case GR_GL_ARRAY_BUFFER:
215 ctx->fCurrArrayBuffer = buffer;
217 case GR_GL_ELEMENT_ARRAY_BUFFER:
218 ctx->fCurrElementArrayBuffer = buffer;
223 // deleting a bound buffer has the side effect of binding 0
224 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) {
225 ThreadContext* ctx = ThreadContext::Get();
226 for (int i = 0; i < n; ++i) {
227 if (ids[i] == ctx->fCurrArrayBuffer) {
228 ctx->fCurrArrayBuffer = 0;
230 if (ids[i] == ctx->fCurrElementArrayBuffer) {
231 ctx->fCurrElementArrayBuffer = 0;
234 BufferObj* buffer = ctx->fBufferManager.lookUp(ids[i]);
235 ctx->fBufferManager.free(buffer);
239 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBufferRange(GrGLenum target, GrGLintptr offset,
240 GrGLsizeiptr length, GrGLbitfield access) {
241 ThreadContext* ctx = ThreadContext::Get();
244 case GR_GL_ARRAY_BUFFER:
245 id = ctx->fCurrArrayBuffer;
247 case GR_GL_ELEMENT_ARRAY_BUFFER:
248 id = ctx->fCurrElementArrayBuffer;
253 // We just ignore the offset and length here.
254 BufferObj* buffer = ctx->fBufferManager.lookUp(id);
255 SkASSERT(!buffer->mapped());
256 buffer->setMapped(true);
257 return buffer->dataPtr();
262 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
263 ThreadContext* ctx = ThreadContext::Get();
266 case GR_GL_ARRAY_BUFFER:
267 id = ctx->fCurrArrayBuffer;
269 case GR_GL_ELEMENT_ARRAY_BUFFER:
270 id = ctx->fCurrElementArrayBuffer;
275 BufferObj* buffer = ctx->fBufferManager.lookUp(id);
276 SkASSERT(!buffer->mapped());
277 buffer->setMapped(true);
278 return buffer->dataPtr();
282 return NULL; // no buffer bound to target
285 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFlushMappedBufferRange(GrGLenum target,
287 GrGLsizeiptr length) {}
290 GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) {
291 ThreadContext* ctx = ThreadContext::Get();
294 case GR_GL_ARRAY_BUFFER:
295 id = ctx->fCurrArrayBuffer;
297 case GR_GL_ELEMENT_ARRAY_BUFFER:
298 id = ctx->fCurrElementArrayBuffer;
302 BufferObj* buffer = ctx->fBufferManager.lookUp(id);
303 SkASSERT(buffer->mapped());
304 buffer->setMapped(false);
308 GrAlwaysAssert(false);
309 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
312 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {
313 ThreadContext* ctx = ThreadContext::Get();
315 case GR_GL_BUFFER_MAPPED: {
316 *params = GR_GL_FALSE;
319 case GR_GL_ARRAY_BUFFER:
320 id = ctx->fCurrArrayBuffer;
322 case GR_GL_ELEMENT_ARRAY_BUFFER:
323 id = ctx->fCurrElementArrayBuffer;
327 BufferObj* buffer = ctx->fBufferManager.lookUp(id);
328 if (buffer->mapped()) {
329 *params = GR_GL_TRUE;
334 SkFAIL("Unexpected pname to GetBufferParamateriv");
339 } // end anonymous namespace
341 const GrGLInterface* GrGLCreateNullInterface() {
342 GrGLInterface* interface = SkNEW(GrGLInterface);
344 interface->fStandard = kGL_GrGLStandard;
346 GrGLInterface::Functions* functions = &interface->fFunctions;
347 functions->fActiveTexture = nullGLActiveTexture;
348 functions->fAttachShader = nullGLAttachShader;
349 functions->fBeginQuery = nullGLBeginQuery;
350 functions->fBindAttribLocation = nullGLBindAttribLocation;
351 functions->fBindBuffer = nullGLBindBuffer;
352 functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
353 functions->fBindTexture = nullGLBindTexture;
354 functions->fBindVertexArray = nullGLBindVertexArray;
355 functions->fBlendColor = noOpGLBlendColor;
356 functions->fBlendFunc = noOpGLBlendFunc;
357 functions->fBufferData = nullGLBufferData;
358 functions->fBufferSubData = noOpGLBufferSubData;
359 functions->fClear = noOpGLClear;
360 functions->fClearColor = noOpGLClearColor;
361 functions->fClearStencil = noOpGLClearStencil;
362 functions->fColorMask = noOpGLColorMask;
363 functions->fCompileShader = noOpGLCompileShader;
364 functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
365 functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
366 functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
367 functions->fCreateProgram = nullGLCreateProgram;
368 functions->fCreateShader = nullGLCreateShader;
369 functions->fCullFace = noOpGLCullFace;
370 functions->fDeleteBuffers = nullGLDeleteBuffers;
371 functions->fDeleteProgram = nullGLDelete;
372 functions->fDeleteQueries = noOpGLDeleteIds;
373 functions->fDeleteShader = nullGLDelete;
374 functions->fDeleteTextures = noOpGLDeleteIds;
375 functions->fDeleteVertexArrays = noOpGLDeleteIds;
376 functions->fDepthMask = noOpGLDepthMask;
377 functions->fDisable = noOpGLDisable;
378 functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
379 functions->fDrawArrays = noOpGLDrawArrays;
380 functions->fDrawBuffer = noOpGLDrawBuffer;
381 functions->fDrawBuffers = noOpGLDrawBuffers;
382 functions->fDrawElements = noOpGLDrawElements;
383 functions->fEnable = noOpGLEnable;
384 functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
385 functions->fEndQuery = noOpGLEndQuery;
386 functions->fFinish = noOpGLFinish;
387 functions->fFlush = noOpGLFlush;
388 functions->fFlushMappedBufferRange = nullGLFlushMappedBufferRange;
389 functions->fFrontFace = noOpGLFrontFace;
390 functions->fGenBuffers = nullGLGenBuffers;
391 functions->fGenerateMipmap = nullGLGenerateMipmap;
392 functions->fGenQueries = noOpGLGenIds;
393 functions->fGenTextures = noOpGLGenIds;
394 functions->fGenVertexArrays = noOpGLGenIds;
395 functions->fGetBufferParameteriv = nullGLGetBufferParameteriv;
396 functions->fGetError = noOpGLGetError;
397 functions->fGetIntegerv = noOpGLGetIntegerv;
398 functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
399 functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
400 functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
401 functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
402 functions->fGetQueryiv = noOpGLGetQueryiv;
403 functions->fGetProgramInfoLog = noOpGLGetInfoLog;
404 functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
405 functions->fGetShaderInfoLog = noOpGLGetInfoLog;
406 functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
407 functions->fGetString = noOpGLGetString;
408 functions->fGetStringi = noOpGLGetStringi;
409 functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
410 functions->fGetUniformLocation = noOpGLGetUniformLocation;
411 functions->fInsertEventMarker = noOpGLInsertEventMarker;
412 functions->fLineWidth = noOpGLLineWidth;
413 functions->fLinkProgram = noOpGLLinkProgram;
414 functions->fMapBuffer = nullGLMapBuffer;
415 functions->fMapBufferRange = nullGLMapBufferRange;
416 functions->fPixelStorei = nullGLPixelStorei;
417 functions->fPopGroupMarker = noOpGLPopGroupMarker;
418 functions->fPushGroupMarker = noOpGLPushGroupMarker;
419 functions->fQueryCounter = noOpGLQueryCounter;
420 functions->fReadBuffer = noOpGLReadBuffer;
421 functions->fReadPixels = nullGLReadPixels;
422 functions->fScissor = noOpGLScissor;
423 functions->fShaderSource = noOpGLShaderSource;
424 functions->fStencilFunc = noOpGLStencilFunc;
425 functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
426 functions->fStencilMask = noOpGLStencilMask;
427 functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
428 functions->fStencilOp = noOpGLStencilOp;
429 functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
430 functions->fTexImage2D = noOpGLTexImage2D;
431 functions->fTexParameteri = noOpGLTexParameteri;
432 functions->fTexParameteriv = noOpGLTexParameteriv;
433 functions->fTexSubImage2D = noOpGLTexSubImage2D;
434 functions->fTexStorage2D = noOpGLTexStorage2D;
435 functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
436 functions->fUniform1f = noOpGLUniform1f;
437 functions->fUniform1i = noOpGLUniform1i;
438 functions->fUniform1fv = noOpGLUniform1fv;
439 functions->fUniform1iv = noOpGLUniform1iv;
440 functions->fUniform2f = noOpGLUniform2f;
441 functions->fUniform2i = noOpGLUniform2i;
442 functions->fUniform2fv = noOpGLUniform2fv;
443 functions->fUniform2iv = noOpGLUniform2iv;
444 functions->fUniform3f = noOpGLUniform3f;
445 functions->fUniform3i = noOpGLUniform3i;
446 functions->fUniform3fv = noOpGLUniform3fv;
447 functions->fUniform3iv = noOpGLUniform3iv;
448 functions->fUniform4f = noOpGLUniform4f;
449 functions->fUniform4i = noOpGLUniform4i;
450 functions->fUniform4fv = noOpGLUniform4fv;
451 functions->fUniform4iv = noOpGLUniform4iv;
452 functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
453 functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
454 functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
455 functions->fUnmapBuffer = nullGLUnmapBuffer;
456 functions->fUseProgram = nullGLUseProgram;
457 functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
458 functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
459 functions->fViewport = nullGLViewport;
460 functions->fBindFramebuffer = nullGLBindFramebuffer;
461 functions->fBindRenderbuffer = nullGLBindRenderbuffer;
462 functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
463 functions->fDeleteFramebuffers = nullGLDeleteFramebuffers;
464 functions->fDeleteRenderbuffers = nullGLDeleteRenderbuffers;
465 functions->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer;
466 functions->fFramebufferTexture2D = nullGLFramebufferTexture2D;
467 functions->fGenFramebuffers = noOpGLGenIds;
468 functions->fGenRenderbuffers = noOpGLGenIds;
469 functions->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv;
470 functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
471 functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
472 functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample;
473 functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
474 functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer;
475 functions->fMatrixLoadf = noOpGLMatrixLoadf;
476 functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
477 functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed;
479 interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
480 functions->fGetIntegerv);