michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "gl/GrGLInterface.h" michael@0: #include "GrGLDefines.h" michael@0: #include "SkTDArray.h" michael@0: #include "GrGLNoOpInterface.h" michael@0: michael@0: // Functions not declared in GrGLBogusInterface.h (not common with the Debug GL interface). michael@0: michael@0: namespace { // added to suppress 'no previous prototype' warning michael@0: michael@0: class GrBufferObj { michael@0: public: michael@0: GrBufferObj(GrGLuint id) : fID(id), fDataPtr(NULL), fSize(0), fMapped(false) { michael@0: } michael@0: ~GrBufferObj() { SkDELETE_ARRAY(fDataPtr); } michael@0: michael@0: void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { michael@0: if (NULL != fDataPtr) { michael@0: SkASSERT(0 != fSize); michael@0: SkDELETE_ARRAY(fDataPtr); michael@0: } michael@0: michael@0: fSize = size; michael@0: fDataPtr = SkNEW_ARRAY(char, size); michael@0: } michael@0: michael@0: GrGLuint id() const { return fID; } michael@0: GrGLchar* dataPtr() { return fDataPtr; } michael@0: GrGLsizeiptr size() const { return fSize; } michael@0: michael@0: void setMapped(bool mapped) { fMapped = mapped; } michael@0: bool mapped() const { return fMapped; } michael@0: michael@0: private: michael@0: GrGLuint fID; michael@0: GrGLchar* fDataPtr; michael@0: GrGLsizeiptr fSize; // size in bytes michael@0: bool fMapped; michael@0: }; michael@0: michael@0: // In debug builds we do asserts that ensure we agree with GL about when a buffer michael@0: // is mapped. michael@0: static SkTDArray gBuffers; // slot 0 is reserved for head of free list michael@0: static GrGLuint gCurrArrayBuffer; michael@0: static GrGLuint gCurrElementArrayBuffer; michael@0: michael@0: static GrBufferObj* look_up(GrGLuint id) { michael@0: GrBufferObj* buffer = gBuffers[id]; michael@0: SkASSERT(NULL != buffer && buffer->id() == id); michael@0: return buffer; michael@0: } michael@0: michael@0: static GrBufferObj* create_buffer() { michael@0: if (0 == gBuffers.count()) { michael@0: // slot zero is reserved for the head of the free list michael@0: *gBuffers.append() = NULL; michael@0: } michael@0: michael@0: GrGLuint id; michael@0: GrBufferObj* buffer; michael@0: michael@0: if (NULL == gBuffers[0]) { michael@0: // no free slots - create a new one michael@0: id = gBuffers.count(); michael@0: buffer = SkNEW_ARGS(GrBufferObj, (id)); michael@0: gBuffers.append(1, &buffer); michael@0: } else { michael@0: // recycle a slot from the free list michael@0: id = SkTCast(gBuffers[0]); michael@0: gBuffers[0] = gBuffers[id]; michael@0: michael@0: buffer = SkNEW_ARGS(GrBufferObj, (id)); michael@0: gBuffers[id] = buffer; michael@0: } michael@0: michael@0: return buffer; michael@0: } michael@0: michael@0: static void delete_buffer(GrBufferObj* buffer) { michael@0: SkASSERT(gBuffers.count() > 0); michael@0: michael@0: GrGLuint id = buffer->id(); michael@0: SkDELETE(buffer); michael@0: michael@0: // Add this slot to the free list michael@0: gBuffers[id] = gBuffers[0]; michael@0: gBuffers[0] = SkTCast((const void*)(intptr_t)id); michael@0: } michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLAttachShader(GrGLuint program, GrGLuint shader) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBeginQuery(GrGLenum target, GrGLuint id) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindTexture(GrGLenum target, GrGLuint texture) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindVertexArray(GrGLuint id) {} michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenBuffers(GrGLsizei n, GrGLuint* ids) { michael@0: michael@0: for (int i = 0; i < n; ++i) { michael@0: GrBufferObj* buffer = create_buffer(); michael@0: ids[i] = buffer->id(); michael@0: } michael@0: } michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenerateMipmap(GrGLenum target) {} michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBufferData(GrGLenum target, michael@0: GrGLsizeiptr size, michael@0: const GrGLvoid* data, michael@0: GrGLenum usage) { michael@0: GrGLuint id = 0; michael@0: michael@0: switch (target) { michael@0: case GR_GL_ARRAY_BUFFER: michael@0: id = gCurrArrayBuffer; michael@0: break; michael@0: case GR_GL_ELEMENT_ARRAY_BUFFER: michael@0: id = gCurrElementArrayBuffer; michael@0: break; michael@0: default: michael@0: GrCrash("Unexpected target to nullGLBufferData"); michael@0: break; michael@0: } michael@0: michael@0: if (id > 0) { michael@0: GrBufferObj* buffer = look_up(id); michael@0: buffer->allocate(size, (const GrGLchar*) data); michael@0: } michael@0: } michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLPixelStorei(GrGLenum pname, GrGLint param) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLUseProgram(GrGLuint program) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {} michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {} michael@0: michael@0: GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateProgram() { michael@0: static GrGLuint gCurrID = 0; michael@0: return ++gCurrID; michael@0: } michael@0: michael@0: GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateShader(GrGLenum type) { michael@0: static GrGLuint gCurrID = 0; michael@0: return ++gCurrID; michael@0: } michael@0: michael@0: // same delete used for shaders and programs michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLDelete(GrGLuint program) { michael@0: } michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindBuffer(GrGLenum target, GrGLuint buffer) { michael@0: switch (target) { michael@0: case GR_GL_ARRAY_BUFFER: michael@0: gCurrArrayBuffer = buffer; michael@0: break; michael@0: case GR_GL_ELEMENT_ARRAY_BUFFER: michael@0: gCurrElementArrayBuffer = buffer; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // deleting a bound buffer has the side effect of binding 0 michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) { michael@0: for (int i = 0; i < n; ++i) { michael@0: if (ids[i] == gCurrArrayBuffer) { michael@0: gCurrArrayBuffer = 0; michael@0: } michael@0: if (ids[i] == gCurrElementArrayBuffer) { michael@0: gCurrElementArrayBuffer = 0; michael@0: } michael@0: michael@0: GrBufferObj* buffer = look_up(ids[i]); michael@0: delete_buffer(buffer); michael@0: } michael@0: } michael@0: michael@0: GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) { michael@0: michael@0: GrGLuint id = 0; michael@0: switch (target) { michael@0: case GR_GL_ARRAY_BUFFER: michael@0: id = gCurrArrayBuffer; michael@0: break; michael@0: case GR_GL_ELEMENT_ARRAY_BUFFER: michael@0: id = gCurrElementArrayBuffer; michael@0: break; michael@0: } michael@0: michael@0: if (id > 0) { michael@0: GrBufferObj* buffer = look_up(id); michael@0: SkASSERT(!buffer->mapped()); michael@0: buffer->setMapped(true); michael@0: return buffer->dataPtr(); michael@0: } michael@0: michael@0: SkASSERT(false); michael@0: return NULL; // no buffer bound to target michael@0: } michael@0: michael@0: GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) { michael@0: GrGLuint id = 0; michael@0: switch (target) { michael@0: case GR_GL_ARRAY_BUFFER: michael@0: id = gCurrArrayBuffer; michael@0: break; michael@0: case GR_GL_ELEMENT_ARRAY_BUFFER: michael@0: id = gCurrElementArrayBuffer; michael@0: break; michael@0: } michael@0: if (id > 0) { michael@0: GrBufferObj* buffer = look_up(id); michael@0: SkASSERT(buffer->mapped()); michael@0: buffer->setMapped(false); michael@0: return GR_GL_TRUE; michael@0: } michael@0: michael@0: GrAlwaysAssert(false); michael@0: return GR_GL_FALSE; // GR_GL_INVALID_OPERATION; michael@0: } michael@0: michael@0: GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) { michael@0: switch (pname) { michael@0: case GR_GL_BUFFER_MAPPED: { michael@0: *params = GR_GL_FALSE; michael@0: GrGLuint id = 0; michael@0: switch (target) { michael@0: case GR_GL_ARRAY_BUFFER: michael@0: id = gCurrArrayBuffer; michael@0: break; michael@0: case GR_GL_ELEMENT_ARRAY_BUFFER: michael@0: id = gCurrElementArrayBuffer; michael@0: break; michael@0: } michael@0: if (id > 0) { michael@0: GrBufferObj* buffer = look_up(id); michael@0: if (buffer->mapped()) { michael@0: *params = GR_GL_TRUE; michael@0: } michael@0: } michael@0: break; } michael@0: default: michael@0: GrCrash("Unexpected pname to GetBufferParamateriv"); michael@0: break; michael@0: } michael@0: }; michael@0: michael@0: } // end anonymous namespace michael@0: michael@0: const GrGLInterface* GrGLCreateNullInterface() { michael@0: GrGLInterface* interface = SkNEW(GrGLInterface); michael@0: michael@0: interface->fStandard = kGL_GrGLStandard; michael@0: michael@0: GrGLInterface::Functions* functions = &interface->fFunctions; michael@0: functions->fActiveTexture = nullGLActiveTexture; michael@0: functions->fAttachShader = nullGLAttachShader; michael@0: functions->fBeginQuery = nullGLBeginQuery; michael@0: functions->fBindAttribLocation = nullGLBindAttribLocation; michael@0: functions->fBindBuffer = nullGLBindBuffer; michael@0: functions->fBindFragDataLocation = noOpGLBindFragDataLocation; michael@0: functions->fBindTexture = nullGLBindTexture; michael@0: functions->fBindVertexArray = nullGLBindVertexArray; michael@0: functions->fBlendColor = noOpGLBlendColor; michael@0: functions->fBlendFunc = noOpGLBlendFunc; michael@0: functions->fBufferData = nullGLBufferData; michael@0: functions->fBufferSubData = noOpGLBufferSubData; michael@0: functions->fClear = noOpGLClear; michael@0: functions->fClearColor = noOpGLClearColor; michael@0: functions->fClearStencil = noOpGLClearStencil; michael@0: functions->fColorMask = noOpGLColorMask; michael@0: functions->fCompileShader = noOpGLCompileShader; michael@0: functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D; michael@0: functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D; michael@0: functions->fCreateProgram = nullGLCreateProgram; michael@0: functions->fCreateShader = nullGLCreateShader; michael@0: functions->fCullFace = noOpGLCullFace; michael@0: functions->fDeleteBuffers = nullGLDeleteBuffers; michael@0: functions->fDeleteProgram = nullGLDelete; michael@0: functions->fDeleteQueries = noOpGLDeleteIds; michael@0: functions->fDeleteShader = nullGLDelete; michael@0: functions->fDeleteTextures = noOpGLDeleteIds; michael@0: functions->fDeleteVertexArrays = noOpGLDeleteIds; michael@0: functions->fDepthMask = noOpGLDepthMask; michael@0: functions->fDisable = noOpGLDisable; michael@0: functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray; michael@0: functions->fDrawArrays = noOpGLDrawArrays; michael@0: functions->fDrawBuffer = noOpGLDrawBuffer; michael@0: functions->fDrawBuffers = noOpGLDrawBuffers; michael@0: functions->fDrawElements = noOpGLDrawElements; michael@0: functions->fEnable = noOpGLEnable; michael@0: functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray; michael@0: functions->fEndQuery = noOpGLEndQuery; michael@0: functions->fFinish = noOpGLFinish; michael@0: functions->fFlush = noOpGLFlush; michael@0: functions->fFrontFace = noOpGLFrontFace; michael@0: functions->fGenBuffers = nullGLGenBuffers; michael@0: functions->fGenerateMipmap = nullGLGenerateMipmap; michael@0: functions->fGenQueries = noOpGLGenIds; michael@0: functions->fGenTextures = noOpGLGenIds; michael@0: functions->fGenVertexArrays = noOpGLGenIds; michael@0: functions->fGetBufferParameteriv = nullGLGetBufferParameteriv; michael@0: functions->fGetError = noOpGLGetError; michael@0: functions->fGetIntegerv = noOpGLGetIntegerv; michael@0: functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v; michael@0: functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv; michael@0: functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v; michael@0: functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv; michael@0: functions->fGetQueryiv = noOpGLGetQueryiv; michael@0: functions->fGetProgramInfoLog = noOpGLGetInfoLog; michael@0: functions->fGetProgramiv = noOpGLGetShaderOrProgramiv; michael@0: functions->fGetShaderInfoLog = noOpGLGetInfoLog; michael@0: functions->fGetShaderiv = noOpGLGetShaderOrProgramiv; michael@0: functions->fGetString = noOpGLGetString; michael@0: functions->fGetStringi = noOpGLGetStringi; michael@0: functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv; michael@0: functions->fGetUniformLocation = noOpGLGetUniformLocation; michael@0: functions->fInsertEventMarker = noOpGLInsertEventMarker; michael@0: functions->fLoadIdentity = noOpGLLoadIdentity; michael@0: functions->fLoadMatrixf = noOpGLLoadMatrixf; michael@0: functions->fLineWidth = noOpGLLineWidth; michael@0: functions->fLinkProgram = noOpGLLinkProgram; michael@0: functions->fMatrixMode = noOpGLMatrixMode; michael@0: functions->fPixelStorei = nullGLPixelStorei; michael@0: functions->fPopGroupMarker = noOpGLPopGroupMarker; michael@0: functions->fPushGroupMarker = noOpGLPushGroupMarker; michael@0: functions->fQueryCounter = noOpGLQueryCounter; michael@0: functions->fReadBuffer = noOpGLReadBuffer; michael@0: functions->fReadPixels = nullGLReadPixels; michael@0: functions->fScissor = noOpGLScissor; michael@0: functions->fShaderSource = noOpGLShaderSource; michael@0: functions->fStencilFunc = noOpGLStencilFunc; michael@0: functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate; michael@0: functions->fStencilMask = noOpGLStencilMask; michael@0: functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate; michael@0: functions->fStencilOp = noOpGLStencilOp; michael@0: functions->fStencilOpSeparate = noOpGLStencilOpSeparate; michael@0: functions->fTexGenfv = noOpGLTexGenfv; michael@0: functions->fTexGeni = noOpGLTexGeni; michael@0: functions->fTexImage2D = noOpGLTexImage2D; michael@0: functions->fTexParameteri = noOpGLTexParameteri; michael@0: functions->fTexParameteriv = noOpGLTexParameteriv; michael@0: functions->fTexSubImage2D = noOpGLTexSubImage2D; michael@0: functions->fTexStorage2D = noOpGLTexStorage2D; michael@0: functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer; michael@0: functions->fUniform1f = noOpGLUniform1f; michael@0: functions->fUniform1i = noOpGLUniform1i; michael@0: functions->fUniform1fv = noOpGLUniform1fv; michael@0: functions->fUniform1iv = noOpGLUniform1iv; michael@0: functions->fUniform2f = noOpGLUniform2f; michael@0: functions->fUniform2i = noOpGLUniform2i; michael@0: functions->fUniform2fv = noOpGLUniform2fv; michael@0: functions->fUniform2iv = noOpGLUniform2iv; michael@0: functions->fUniform3f = noOpGLUniform3f; michael@0: functions->fUniform3i = noOpGLUniform3i; michael@0: functions->fUniform3fv = noOpGLUniform3fv; michael@0: functions->fUniform3iv = noOpGLUniform3iv; michael@0: functions->fUniform4f = noOpGLUniform4f; michael@0: functions->fUniform4i = noOpGLUniform4i; michael@0: functions->fUniform4fv = noOpGLUniform4fv; michael@0: functions->fUniform4iv = noOpGLUniform4iv; michael@0: functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv; michael@0: functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv; michael@0: functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv; michael@0: functions->fUseProgram = nullGLUseProgram; michael@0: functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv; michael@0: functions->fVertexAttribPointer = noOpGLVertexAttribPointer; michael@0: functions->fViewport = nullGLViewport; michael@0: functions->fBindFramebuffer = nullGLBindFramebuffer; michael@0: functions->fBindRenderbuffer = nullGLBindRenderbuffer; michael@0: functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus; michael@0: functions->fDeleteFramebuffers = nullGLDeleteFramebuffers; michael@0: functions->fDeleteRenderbuffers = nullGLDeleteRenderbuffers; michael@0: functions->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer; michael@0: functions->fFramebufferTexture2D = nullGLFramebufferTexture2D; michael@0: functions->fGenFramebuffers = noOpGLGenIds; michael@0: functions->fGenRenderbuffers = noOpGLGenIds; michael@0: functions->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv; michael@0: functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv; michael@0: functions->fRenderbufferStorage = noOpGLRenderbufferStorage; michael@0: functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample; michael@0: functions->fBlitFramebuffer = noOpGLBlitFramebuffer; michael@0: functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer; michael@0: functions->fMapBuffer = nullGLMapBuffer; michael@0: functions->fUnmapBuffer = nullGLUnmapBuffer; michael@0: functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed; michael@0: michael@0: interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi, michael@0: functions->fGetIntegerv); michael@0: return interface; michael@0: }