EXTERN_PART GL_APICALL GLconstubyteptr GL_APIENTRY glGetStringi(GLenum name, GLint index) { GET_CTX_V2_RET(0); GLconstubyteptr glGetStringiRET = ctx->dispatcher().glGetStringi(name, index); return glGetStringiRET; } GL_APICALL void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays) { glGenVertexArraysOES(n, arrays); } GL_APICALL void GL_APIENTRY glBindVertexArray(GLuint array) { glBindVertexArrayOES(array); } GL_APICALL void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint * arrays) { glDeleteVertexArraysOES(n, arrays); } GL_APICALL GLboolean GL_APIENTRY glIsVertexArray(GLuint array) { return glIsVertexArrayOES(array); } GL_APICALL void * GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { GET_CTX_V2_RET(0); RET_AND_SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM,0); void * glMapBufferRangeRET = ctx->dispatcher().glMapBufferRange(target, offset, length, access); return glMapBufferRangeRET; } GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) { GET_CTX_V2_RET(0); RET_AND_SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM,0); GLboolean glUnmapBufferRET = ctx->dispatcher().glUnmapBuffer(target); return glUnmapBufferRET; } GL_APICALL void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM); ctx->dispatcher().glFlushMappedBufferRange(target, offset, length); } GL_APICALL void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM); ctx->bindBuffer(target, buffer); ctx->bindIndexedBuffer(target, index, buffer, offset, size); if (ctx->shareGroup().get()) { const GLuint globalBufferName = ctx->shareGroup()->getGlobalName(NamedObjectType::VERTEXBUFFER, buffer); ctx->dispatcher().glBindBufferRange(target, index, globalBufferName, offset, size); } } GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM); ctx->bindBuffer(target, buffer); ctx->bindIndexedBuffer(target, index, buffer); if (ctx->shareGroup().get()) { const GLuint globalBufferName = ctx->shareGroup()->getGlobalName(NamedObjectType::VERTEXBUFFER, buffer); ctx->dispatcher().glBindBufferBase(target, index, globalBufferName); } } GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) { GET_CTX_V2(); ctx->dispatcher().glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size); } GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawBuffer, const GLint * value) { GET_CTX_V2(); ctx->dispatcher().glClearBufferiv(buffer, drawBuffer, value); } GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawBuffer, const GLuint * value) { GET_CTX_V2(); ctx->dispatcher().glClearBufferuiv(buffer, drawBuffer, value); } GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawBuffer, const GLfloat * value) { GET_CTX_V2(); ctx->dispatcher().glClearBufferfv(buffer, drawBuffer, value); } GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil) { GET_CTX_V2(); ctx->dispatcher().glClearBufferfi(buffer, drawBuffer, depth, stencil); } GL_APICALL void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum value, GLint64 * data) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM); ctx->dispatcher().glGetBufferParameteri64v(target, value, data); } GL_APICALL void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid ** params) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::bufferTarget(ctx, target),GL_INVALID_ENUM); ctx->dispatcher().glGetBufferPointerv(target, pname, params); } GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glUniformBlockBinding(globalProgramName, uniformBlockIndex, uniformBlockBinding); } } GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar * uniformBlockName) { GET_CTX_V2_RET(0); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); GLuint glGetUniformBlockIndexRET = ctx->dispatcher().glGetUniformBlockIndex(globalProgramName, uniformBlockName); return glGetUniformBlockIndexRET; } else return 0; } EXTERN_PART GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint * uniformIndices) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetUniformIndices(globalProgramName, uniformCount, uniformNames, uniformIndices); } } GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetActiveUniformBlockiv(globalProgramName, uniformBlockIndex, pname, params); } } GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetActiveUniformBlockName(globalProgramName, uniformBlockIndex, bufSize, length, uniformBlockName); } } GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform1ui(hostLoc, v0); } GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform2ui(hostLoc, v0, v1); } GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform3ui(hostLoc, v0, v1, v2); } EXTERN_PART GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform4ui(hostLoc, v0, v1, v2, v3); } GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform1uiv(hostLoc, count, value); } GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform2uiv(hostLoc, count, value); } GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform3uiv(hostLoc, count, value); } GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniform4uiv(hostLoc, count, value); } GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix2x3fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix3x2fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix2x4fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix4x2fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix3x4fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { GET_CTX_V2(); int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glUniformMatrix4x3fv(hostLoc, count, transpose, value); } GL_APICALL void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint * params) { GET_CTX_V2(); SET_ERROR_IF(location < 0,GL_INVALID_OPERATION); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE); auto objData = ctx->shareGroup()->getObjectData( NamedObjectType::SHADER_OR_PROGRAM, program); SET_ERROR_IF(objData->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION); ProgramData* pData = (ProgramData *)objData; (void)pData; #if !defined(TOLERATE_PROGRAM_LINK_ERROR) || !TOLERATE_PROGRAM_LINK_ERROR SET_ERROR_IF(!pData->getLinkStatus(), GL_INVALID_OPERATION); #endif int hostLoc = s_getHostLocOrSetError(ctx, location); SET_ERROR_IF(hostLoc < -1, GL_INVALID_OPERATION); ctx->dispatcher().glGetUniformuiv(globalProgramName, hostLoc, params); } } GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetActiveUniformsiv(globalProgramName, uniformCount, uniformIndices, pname, params); } } GL_APICALL void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) { GET_CTX_V2(); ctx->dispatcher().glVertexAttribI4i(index, v0, v1, v2, v3); } GL_APICALL void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { GET_CTX_V2(); ctx->dispatcher().glVertexAttribI4ui(index, v0, v1, v2, v3); } GL_APICALL void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint * v) { GET_CTX_V2(); ctx->dispatcher().glVertexAttribI4iv(index, v); } GL_APICALL void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint * v) { GET_CTX_V2(); ctx->dispatcher().glVertexAttribI4uiv(index, v); } GL_APICALL void GL_APIENTRY glVertexAttribIPointerWithDataSize(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* ptr, GLsizei dataSize) { GET_CTX_V2(); SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); s_glPrepareVertexAttribPointer(ctx, index, size, type, false, stride, ptr, dataSize, true); if (ctx->isBindedBuffer(GL_ARRAY_BUFFER)) { ctx->dispatcher().glVertexAttribIPointer(index, size, type, stride, ptr); } } GL_APICALL void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { GET_CTX_V2(); SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); s_glPrepareVertexAttribPointer(ctx, index, size, type, false, stride, pointer, 0, true); if (ctx->isBindedBuffer(GL_ARRAY_BUFFER)) { ctx->dispatcher().glVertexAttribIPointer(index, size, type, stride, pointer); } } GL_APICALL void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint * params) { GET_CTX_V2(); ctx->dispatcher().glGetVertexAttribIiv(index, pname, params); } GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint * params) { GET_CTX_V2(); ctx->dispatcher().glGetVertexAttribIuiv(index, pname, params); } GL_APICALL void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) { GET_CTX_V2(); SET_ERROR_IF((!GLESv2Validate::arrayIndex(ctx,index)),GL_INVALID_VALUE); ctx->setVertexAttribBindingIndex(index, index); ctx->setVertexAttribDivisor(index, divisor); ctx->dispatcher().glVertexAttribDivisor(index, divisor); } GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { GET_CTX_V2(); SET_ERROR_IF(count < 0,GL_INVALID_VALUE) SET_ERROR_IF(!(GLESv2Validate::drawMode(mode)),GL_INVALID_ENUM); if (ctx->vertexAttributesBufferBacked()) { s_glDrawPre(ctx, mode); ctx->dispatcher().glDrawArraysInstanced(mode, first, count, primcount); s_glDrawPost(ctx, mode); } else { ctx->drawWithEmulations( GLESv2Context::DrawCallCmd::ArraysInstanced, mode, first, count, 0, nullptr, primcount, 0, 0 /* type, indices, start, end unused */); } } GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) { GET_CTX_V2(); SET_ERROR_IF(count < 0,GL_INVALID_VALUE) SET_ERROR_IF(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM); if (ctx->isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER) && ctx->vertexAttributesBufferBacked()) { s_glDrawPre(ctx, mode, type); ctx->dispatcher().glDrawElementsInstanced(mode, count, type, indices, primcount); s_glDrawPost(ctx, mode); } else { ctx->drawWithEmulations( GLESv2Context::DrawCallCmd::ElementsInstanced, mode, 0 /* first (unused) */, count, type, indices, primcount, 0, 0 /* start, end (unused) */); } } GL_APICALL void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) { GET_CTX_V2(); SET_ERROR_IF(count < 0,GL_INVALID_VALUE) SET_ERROR_IF(!(GLESv2Validate::drawMode(mode) && GLESv2Validate::drawType(type)),GL_INVALID_ENUM); if (ctx->isBindedBuffer(GL_ELEMENT_ARRAY_BUFFER) && ctx->vertexAttributesBufferBacked()) { s_glDrawPre(ctx, mode, type); ctx->dispatcher().glDrawRangeElements(mode, start, end, count, type, indices); s_glDrawPost(ctx, mode); } else { ctx->drawWithEmulations( GLESv2Context::DrawCallCmd::RangeElements, mode, 0 /* first (unused) */, count, type, indices, 0 /* primcount (unused) */, start, end); } } // GuestSyncs: Tracks the system-wide set of GL syncs, puts them in a // distinguished namespace from EGL syncs. This is in its own class as opposed // to a NameSpace because a) no real need to snapshot save/load those and b) it // needs to span all contexts and give the same names across the entire system, // as sync objects live outside of GL context state. // This is to fix dEQP negative_api tests that delete sync object 0x1 but fail due // to it colliding with an EGL fence name. class GuestSyncs { public: GuestSyncs() { } GLsync create(GLsync newHostSync) { GLsync res = (GLsync)(uintptr_t)mNameCounter; mSyncs[res] = newHostSync; mNameCounter++; if (!mNameCounter) mNameCounter = 0x1000; return res; } GLsync lookupWithError(GLsync guestSync, GLint* err) { *err = GL_NO_ERROR; GLsync host = (GLsync)0x0; const auto& it = mSyncs.find(guestSync); if (it == mSyncs.end()) { *err = GL_INVALID_VALUE; return host; } else { host = it->second; } return host; } GLsync removeWithError(GLsync guestSyncToDelete, GLint* err) { *err = GL_NO_ERROR; GLsync host = (GLsync)0x0; if (!guestSyncToDelete) { return host; } const auto& it = mSyncs.find(guestSyncToDelete); if (it == mSyncs.end()) { *err = GL_INVALID_VALUE; return host; } else { host = it->second; } mSyncs.erase(it); return host; } bool isSync(GLsync guestSync) { return mSyncs.find(guestSync) != mSyncs.end(); } android::base::Lock& lock() { return mLock; } private: std::unordered_map mSyncs; mutable android::base::Lock mLock; uint32_t mNameCounter = 0x1; }; static GuestSyncs* sSyncs() { static GuestSyncs* s = new GuestSyncs; return s; } static GLsync internal_glFenceSync(GLenum condition, GLbitfield flags) { GET_CTX_V2_RET(0); if (!ctx->dispatcher().glFenceSync) { ctx->dispatcher().glFinish(); return (GLsync)0x42; } GLsync glFenceSyncRET = ctx->dispatcher().glFenceSync(condition, flags); return glFenceSyncRET; } static GLenum internal_glClientWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout) { GET_CTX_V2_RET(GL_WAIT_FAILED); if (!ctx->dispatcher().glFenceSync) { return GL_ALREADY_SIGNALED; } GLenum glClientWaitSyncRET = ctx->dispatcher().glClientWaitSync(wait_on, flags, timeout); return glClientWaitSyncRET; } static void internal_glWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout) { GET_CTX_V2(); if (!ctx->dispatcher().glFenceSync) { return; } ctx->dispatcher().glWaitSync(wait_on, flags, timeout); } static void internal_glDeleteSync(GLsync to_delete) { GET_CTX_V2(); if (!ctx->dispatcher().glFenceSync) { return; } ctx->dispatcher().glDeleteSync(to_delete); } static void internal_glGetSynciv(GLsync sync, GLenum pname, GLsizei bufsize, GLsizei *length, GLint *values) { GET_CTX_V2(); if (!ctx->dispatcher().glGetSynciv) { if (bufsize < sizeof(GLint)) return; switch (pname) { case GL_OBJECT_TYPE: if (length) *length = sizeof(GLint); *values = GL_SYNC_FENCE; break; case GL_SYNC_CONDITION: if (length) *length = sizeof(GLint); *values = GL_SYNC_GPU_COMMANDS_COMPLETE; break; case GL_SYNC_FLAGS: // Not supported break; case GL_SYNC_STATUS: if (length) *length = sizeof(GLint); *values = GL_SIGNALED; break; default: break; } return; } ctx->dispatcher().glGetSynciv(sync, pname, bufsize, length, values); } GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags) { GET_CTX_V2_RET(0); android::base::AutoLock lock(sSyncs()->lock()); GLsync hostSync = internal_glFenceSync(condition, flags); GLsync guestSync = sSyncs()->create(hostSync); return guestSync; } GL_APICALL GLenum GL_APIENTRY glClientWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout) { GET_CTX_V2_RET(GL_WAIT_FAILED); GLint err = GL_NO_ERROR; android::base::AutoLock lock(sSyncs()->lock()); GLsync hostSync = sSyncs()->lookupWithError(wait_on, &err); RET_AND_SET_ERROR_IF(err != GL_NO_ERROR, err, GL_WAIT_FAILED); return internal_glClientWaitSync(hostSync, flags, timeout); } GL_APICALL void GL_APIENTRY glWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout) { GET_CTX_V2(); GLint err = GL_NO_ERROR; android::base::AutoLock lock(sSyncs()->lock()); GLsync hostSync = sSyncs()->lookupWithError(wait_on, &err); SET_ERROR_IF(err != GL_NO_ERROR, err); internal_glWaitSync(hostSync, flags, timeout); } GL_APICALL void GL_APIENTRY glDeleteSync(GLsync to_delete) { GET_CTX_V2(); GLint err = GL_NO_ERROR; android::base::AutoLock lock(sSyncs()->lock()); GLsync hostSync = sSyncs()->removeWithError(to_delete, &err); SET_ERROR_IF(err != GL_NO_ERROR, err); internal_glDeleteSync(hostSync); } GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync) { GET_CTX_V2_RET(0); android::base::AutoLock lock(sSyncs()->lock()); return sSyncs()->isSync(sync) ? GL_TRUE : GL_FALSE; } GL_APICALL void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) { GET_CTX_V2(); GLint err = GL_NO_ERROR; android::base::AutoLock lock(sSyncs()->lock()); GLsync hostSync = sSyncs()->lookupWithError(sync, &err); SET_ERROR_IF(err != GL_NO_ERROR, err); ctx->dispatcher().glGetSynciv(hostSync, pname, bufSize, length, values); } GL_APICALL void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum * bufs) { GET_CTX_V2(); if (ctx->isDefaultFBOBound(GL_DRAW_FRAMEBUFFER)) { SET_ERROR_IF(n != 1 || (bufs[0] != GL_NONE && bufs[0] != GL_BACK), GL_INVALID_OPERATION); GLenum emulatedBufs = bufs[0] == GL_NONE ? GL_NONE : GL_COLOR_ATTACHMENT0; ctx->setDefaultFBODrawBuffer(emulatedBufs); ctx->dispatcher().glDrawBuffers(1, &emulatedBufs); } else { GLuint framebuffer = ctx->getFramebufferBinding(GL_DRAW_FRAMEBUFFER); FramebufferData* fbObj = ctx->getFBOData(framebuffer); fbObj->setDrawBuffers(n, bufs); ctx->dispatcher().glDrawBuffers(n, bufs); } } GL_APICALL void GL_APIENTRY glReadBuffer(GLenum src) { GET_CTX_V2(); // if default fbo is bound and src is GL_BACK, // use GL_COLOR_ATTACHMENT0 all of a sudden. // bc we are using fbo emulation. if (ctx->isDefaultFBOBound(GL_READ_FRAMEBUFFER)) { SET_ERROR_IF(src != GL_NONE && src != GL_BACK, GL_INVALID_OPERATION); GLenum emulatedSrc = src == GL_NONE ? GL_NONE : GL_COLOR_ATTACHMENT0; ctx->setDefaultFBOReadBuffer(emulatedSrc); ctx->dispatcher().glReadBuffer(emulatedSrc); } else { GLuint framebuffer = ctx->getFramebufferBinding(GL_READ_FRAMEBUFFER); FramebufferData* fbObj = ctx->getFBOData(framebuffer); fbObj->setReadBuffers(src); ctx->dispatcher().glReadBuffer(src); } } GL_APICALL void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { GET_CTX_V2(); ctx->dispatcher().glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } static std::vector sGetEmulatedAttachmentList(GLESv2Context* ctx, GLenum target, GLsizei numAttachments, const GLenum* attachments) { std::vector res(numAttachments); memcpy(&res[0], attachments, numAttachments * sizeof(GLenum)); if (!ctx->hasEmulatedDefaultFBO() || !ctx->isDefaultFBOBound(target)) return res; for (int i = 0; i < numAttachments; i++) { if (attachments[i] == GL_COLOR) res[i] = GL_COLOR_ATTACHMENT0; if (attachments[i] == GL_DEPTH) res[i] = GL_DEPTH_ATTACHMENT; if (attachments[i] == GL_STENCIL) res[i] = GL_STENCIL_ATTACHMENT; } return res; } GL_APICALL void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments) { GET_CTX_V2(); SET_ERROR_IF(target != GL_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER, GL_INVALID_ENUM); GLint maxColorAttachments; glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments); for (int i = 0; i < numAttachments; i++) { if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) { SET_ERROR_IF((GLint)(attachments[i] - GL_COLOR_ATTACHMENT0 + 1) > maxColorAttachments, GL_INVALID_OPERATION); } } std::vector emulatedAttachments = sGetEmulatedAttachmentList(ctx, target, numAttachments, attachments); if (ctx->dispatcher().glInvalidateFramebuffer) { ctx->dispatcher().glInvalidateFramebuffer(target, numAttachments, &emulatedAttachments[0]); } else { // If we are missing glInvalidateFramebuffer, just don't do anything and hope things work out. } } GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height) { GET_CTX_V2(); SET_ERROR_IF(target != GL_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER, GL_INVALID_ENUM); GLint maxColorAttachments; glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments); for (int i = 0; i < numAttachments; i++) { if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) { SET_ERROR_IF((GLint)(attachments[i] - GL_COLOR_ATTACHMENT0 + 1) > maxColorAttachments, GL_INVALID_OPERATION); } } std::vector emulatedAttachments = sGetEmulatedAttachmentList(ctx, target, numAttachments, attachments); if (ctx->dispatcher().glInvalidateSubFramebuffer) { ctx->dispatcher().glInvalidateSubFramebuffer(target, numAttachments, &emulatedAttachments[0], x, y, width, height); } else { // If we are missing glInvalidateSubFramebuffer, just don't do anything and hope things work out. } } GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { GET_CTX_V2(); GLenum textarget = GL_TEXTURE_2D_ARRAY; SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(ctx, target) && GLESv2Validate::framebufferAttachment(ctx, attachment)), GL_INVALID_ENUM); SET_ERROR_IF(ctx->isDefaultFBOBound(target), GL_INVALID_OPERATION); if (texture) { if (!ctx->shareGroup()->isObject(NamedObjectType::TEXTURE, texture)) { ctx->shareGroup()->genName(NamedObjectType::TEXTURE, texture); } TextureData* texData = getTextureData(texture); textarget = texData->target; } if (ctx->shareGroup().get()) { const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(NamedObjectType::TEXTURE, texture); ctx->dispatcher().glFramebufferTextureLayer(target, attachment, globalTextureName, level, layer); } GLuint fbName = ctx->getFramebufferBinding(target); auto fbObj = ctx->getFBOData(fbName); if (fbObj) { fbObj->setAttachment( ctx, attachment, textarget, texture, ObjectDataPtr()); } } GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { GET_CTX_V2(); GLint err = GL_NO_ERROR; internalformat = sPrepareRenderbufferStorage(internalformat, width, height, samples, &err); SET_ERROR_IF(err != GL_NO_ERROR, err); ctx->dispatcher().glRenderbufferStorageMultisample(target, samples, internalformat, width, height); } GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params) { GET_CTX_V2(); ctx->dispatcher().glGetInternalformativ(target, internalformat, pname, bufSize, params); } GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { GET_CTX_V2(); GLint err = GL_NO_ERROR; GLenum format, type; GLESv2Validate::getCompatibleFormatTypeForInternalFormat(internalformat, &format, &type); sPrepareTexImage2D(target, 0, (GLint)internalformat, width, height, 0, format, type, 0, NULL, &type, (GLint*)&internalformat, &err); SET_ERROR_IF(err != GL_NO_ERROR, err); TextureData *texData = getTextureTargetData(target); texData->texStorageLevels = levels; ctx->dispatcher().glTexStorage2D(target, levels, internalformat, width, height); } GL_APICALL void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode) { GET_CTX_V2(); ctx->boundTransformFeedback()->mIsActive = true; ctx->boundTransformFeedback()->mIsPaused = false; ctx->dispatcher().glBeginTransformFeedback(primitiveMode); } GL_APICALL void GL_APIENTRY glEndTransformFeedback() { GET_CTX_V2(); ctx->boundTransformFeedback()->mIsActive = false; ctx->dispatcher().glEndTransformFeedback(); } GL_APICALL void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint * ids) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); for (int i = 0; i < n; i++) { ids[i] = ctx->genTransformFeedbackName(0, true); } } GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint * ids) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); ObjectLocalName boundTransformFeedback = ctx->getTransformFeedbackBinding(); TransformFeedbackData* tfData = ctx->boundTransformFeedback(); if (boundTransformFeedback) { for (GLsizei i = 0; i < n; i++) { SET_ERROR_IF(ids[i] == boundTransformFeedback && tfData->mIsActive, GL_INVALID_OPERATION); } } for (GLsizei i = 0; i < n; i++) { if (ids[i]) { if (boundTransformFeedback == ids[i]) { assert(!tfData->mIsActive); ctx->bindTransformFeedback(0); } ctx->deleteTransformFeedback(ids[i]); } } } GL_APICALL void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) { GET_CTX_V2(); unsigned int globalName = ctx->getTransformFeedbackGlobalName(id); SET_ERROR_IF(id != 0 && globalName == 0, GL_INVALID_OPERATION); ctx->bindTransformFeedback(id); ctx->dispatcher().glBindTransformFeedback(target, globalName); } GL_APICALL void GL_APIENTRY glPauseTransformFeedback() { GET_CTX_V2(); ctx->boundTransformFeedback()->mIsPaused = true; ctx->dispatcher().glPauseTransformFeedback(); } GL_APICALL void GL_APIENTRY glResumeTransformFeedback() { GET_CTX_V2(); ctx->boundTransformFeedback()->mIsPaused = false; ctx->dispatcher().glResumeTransformFeedback(); } GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) { GET_CTX_V2_RET(0); return ctx->hasBoundTransformFeedback(id); } EXTERN_PART GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glTransformFeedbackVaryings(globalProgramName, count, varyings, bufferMode); } } GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, char * name) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetTransformFeedbackVarying(globalProgramName, index, bufSize, length, size, type, name); } } GL_APICALL void GL_APIENTRY glGenSamplers(GLsizei n, GLuint * samplers) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); if(ctx->shareGroup().get()) { for(int i=0; ishareGroup()->genName(NamedObjectType::SAMPLER, 0, true); ctx->shareGroup()->setObjectData(NamedObjectType::SAMPLER, samplers[i], ObjectDataPtr(new SamplerData())); } } } GL_APICALL void GL_APIENTRY glDeleteSamplers(GLsizei n, const GLuint * samplers) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); if(ctx->shareGroup().get()) { for(int i=0; ishareGroup()->deleteName(NamedObjectType::SAMPLER, samplers[i]); } } } GL_APICALL void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); SET_ERROR_IF(sampler && !globalSampler, GL_INVALID_OPERATION); ctx->setBindSampler(unit, sampler); ctx->dispatcher().glBindSampler(unit, globalSampler); } } GL_APICALL void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName( NamedObjectType::SAMPLER, sampler); SET_ERROR_IF(!globalSampler, GL_INVALID_OPERATION); SamplerData* samplerData = (SamplerData*)ctx->shareGroup()->getObjectData( NamedObjectType::SAMPLER, sampler); samplerData->setParamf(pname, param); ctx->dispatcher().glSamplerParameterf(globalSampler, pname, param); } } GL_APICALL void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName( NamedObjectType::SAMPLER, sampler); SET_ERROR_IF(!globalSampler, GL_INVALID_OPERATION); SamplerData* samplerData = (SamplerData*)ctx->shareGroup()->getObjectData( NamedObjectType::SAMPLER, sampler); samplerData->setParami(pname, param); ctx->dispatcher().glSamplerParameteri(globalSampler, pname, param); } } GL_APICALL void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); ctx->dispatcher().glSamplerParameterfv(globalSampler, pname, params); } } GL_APICALL void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); ctx->dispatcher().glSamplerParameteriv(globalSampler, pname, params); } } GL_APICALL void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); ctx->dispatcher().glGetSamplerParameterfv(globalSampler, pname, params); } } GL_APICALL void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); ctx->dispatcher().glGetSamplerParameteriv(globalSampler, pname, params); } } GL_APICALL GLboolean GL_APIENTRY glIsSampler(GLuint sampler) { GET_CTX_V2_RET(0); if (ctx->shareGroup().get()) { const GLuint globalSampler = ctx->shareGroup()->getGlobalName(NamedObjectType::SAMPLER, sampler); GLboolean glIsSamplerRET = ctx->dispatcher().glIsSampler(globalSampler); return glIsSamplerRET; } else return 0; } GL_APICALL void GL_APIENTRY glGenQueries(GLsizei n, GLuint * queries) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); if(ctx->shareGroup().get()) { for(int i=0; ishareGroup()->genName(NamedObjectType::QUERY, 0, true); } } } GL_APICALL void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint * queries) { GET_CTX_V2(); SET_ERROR_IF(n < 0,GL_INVALID_VALUE); if(ctx->shareGroup().get()) { for(int i=0; ishareGroup()->deleteName(NamedObjectType::QUERY, queries[i]); } } } GL_APICALL void GL_APIENTRY glBeginQuery(GLenum target, GLuint query) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalQuery = ctx->shareGroup()->getGlobalName(NamedObjectType::QUERY, query); ctx->dispatcher().glBeginQuery(target, globalQuery); } } GL_APICALL void GL_APIENTRY glEndQuery(GLenum target) { GET_CTX_V2(); ctx->dispatcher().glEndQuery(target); } GL_APICALL void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint * params) { GET_CTX_V2(); ctx->dispatcher().glGetQueryiv(target, pname, params); } GL_APICALL void GL_APIENTRY glGetQueryObjectuiv(GLuint query, GLenum pname, GLuint * params) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalQuery = ctx->shareGroup()->getGlobalName(NamedObjectType::QUERY, query); ctx->dispatcher().glGetQueryObjectuiv(globalQuery, pname, params); } } GL_APICALL GLboolean GL_APIENTRY glIsQuery(GLuint query) { GET_CTX_V2_RET(0); if (ctx->shareGroup().get()) { const GLuint globalQuery = ctx->shareGroup()->getGlobalName(NamedObjectType::QUERY, query); GLboolean glIsQueryRET = ctx->dispatcher().glIsQuery(globalQuery); return glIsQueryRET; } else return 0; } GL_APICALL void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glProgramParameteri(globalProgramName, pname, value); } } GL_APICALL void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); SET_ERROR_IF(globalProgramName == 0, GL_INVALID_VALUE); auto objData = ctx->shareGroup()->getObjectData(NamedObjectType::SHADER_OR_PROGRAM, program); SET_ERROR_IF(!objData, GL_INVALID_OPERATION); SET_ERROR_IF(objData->getDataType() != PROGRAM_DATA, GL_INVALID_OPERATION); ProgramData* programData = (ProgramData*)objData; ctx->dispatcher().glProgramBinary(globalProgramName, binaryFormat, binary, length); GLint linkStatus = GL_FALSE; ctx->dispatcher().glGetProgramiv(globalProgramName, GL_LINK_STATUS, &linkStatus); programData->setHostLinkStatus(linkStatus); programData->setLinkStatus(linkStatus); GLsizei infoLogLength = 0; ctx->dispatcher().glGetProgramiv(globalProgramName, GL_INFO_LOG_LENGTH, &infoLogLength); if (infoLogLength > 0) { std::vector infoLog(infoLogLength); ctx->dispatcher().glGetProgramInfoLog(globalProgramName, infoLogLength, &infoLogLength, infoLog.data()); if (infoLogLength) { infoLog.resize(infoLogLength); programData->setInfoLog(infoLog.data()); } } } } GL_APICALL void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufsize, GLsizei * length, GLenum * binaryFormat, void * binary) { GET_CTX_V2(); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); ctx->dispatcher().glGetProgramBinary(globalProgramName, bufsize, length, binaryFormat, binary); } } GL_APICALL GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const char * name) { GET_CTX_V2_RET(0); if (ctx->shareGroup().get()) { const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(NamedObjectType::SHADER_OR_PROGRAM, program); GLint glGetFragDataLocationRET = ctx->dispatcher().glGetFragDataLocation(globalProgramName, name); return glGetFragDataLocationRET; } else return 0; } GL_APICALL void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 * data) { GET_CTX_V2(); s_glStateQueryTv(true, pname, data, s_glGetInteger64v_wrapper); } GL_APICALL void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint * data) { GET_CTX_V2(); s_glStateQueryTi_v(target, index, data, s_glGetIntegeri_v_wrapper); } GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 * data) { GET_CTX_V2(); s_glStateQueryTi_v(target, index, data, s_glGetInteger64i_v_wrapper); } GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * data) { GET_CTX_V2(); SET_ERROR_IF(!GLESv2Validate::pixelItnlFrmt(ctx,internalFormat), GL_INVALID_VALUE); SET_ERROR_IF(!GLESv2Validate::isCompressedFormat(internalFormat) && !GLESv2Validate::pixelSizedFrmt(ctx, internalFormat, format, type), GL_INVALID_OPERATION); s_glInitTexImage3D(target, level, internalFormat, width, height, depth, border, format, type); // Desktop OpenGL doesn't support GL_BGRA_EXT as internal format. if (!isGles2Gles() && type == GL_UNSIGNED_BYTE && format == GL_BGRA_EXT && internalFormat == GL_BGRA_EXT) { internalFormat = GL_RGBA; } if (isCoreProfile()) { GLEScontext::prepareCoreProfileEmulatedTexture( getTextureTargetData(target), true, target, format, type, &internalFormat, &format); } ctx->dispatcher().glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data); } GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { GET_CTX_V2(); GLenum format, type; GLESv2Validate::getCompatibleFormatTypeForInternalFormat(internalformat, &format, &type); s_glInitTexImage3D(target, 0, internalformat, width, height, depth, 0, format, type); // Desktop OpenGL doesn't support GL_BGRA_EXT as internal format. if (!isGles2Gles() && type == GL_UNSIGNED_BYTE && format == GL_BGRA_EXT && internalformat == GL_BGRA8_EXT) { internalformat = GL_RGBA8; } TextureData *texData = getTextureTargetData(target); texData->texStorageLevels = levels; ctx->dispatcher().glTexStorage3D(target, levels, internalformat, width, height, depth); } GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * data) { GET_CTX_V2(); if (isCoreProfile() && isCoreProfileEmulatedFormat(format)) { format = getCoreProfileEmulatedFormat(format); } TextureData* texData = getTextureTargetData(target); if (texData) { texData->setMipmapLevelAtLeast(level); texData->makeDirty(); } ctx->dispatcher().glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); } GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data) { GET_CTX_V2(); ctx->dispatcher().glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); if (ctx->shareGroup().get()) { TextureData *texData = getTextureTargetData(target); if (texData) { texData->hasStorage = true; texData->compressed = true; texData->compressedFormat = internalformat; texData->makeDirty(); } } } GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data) { GET_CTX_V2(); TextureData* texData = getTextureTargetData(target); if (texData) { texData->makeDirty(); } ctx->dispatcher().glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); } GL_APICALL void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) { GET_CTX_V2(); TextureData* texData = getTextureTargetData(target); if (texData) { texData->makeDirty(); } ctx->dispatcher().glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); } GL_APICALL void GL_APIENTRY glEnableiEXT(GLenum cap, GLuint index) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setEnablei(cap, index, true); ctx->dispatcher().glEnableiEXT(cap, index); } GL_APICALL void GL_APIENTRY glDisableiEXT(GLenum cap, GLuint index) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setEnablei(cap, index, false); ctx->dispatcher().glDisableiEXT(cap, index); } GL_APICALL void GL_APIENTRY glBlendEquationiEXT(GLuint buf, GLenum mode) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setBlendEquationSeparatei(buf, mode, mode); ctx->dispatcher().glBlendEquationiEXT(buf, mode); } GL_APICALL void GL_APIENTRY glBlendEquationSeparateiEXT(GLuint buf, GLenum modeRGB, GLenum modeAlpha) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setBlendEquationSeparatei(buf, modeRGB, modeAlpha); ctx->dispatcher().glBlendEquationSeparateiEXT(buf, modeRGB, modeAlpha); } GL_APICALL void GL_APIENTRY glBlendFunciEXT(GLuint buf, GLenum sfactor, GLenum dfactor) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setBlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor); ctx->dispatcher().glBlendFunciEXT(buf, sfactor, dfactor); } GL_APICALL void GL_APIENTRY glBlendFuncSeparateiEXT(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setBlendFuncSeparatei(buf, srcRGB, dstRGB, srcAlpha, dstAlpha); ctx->dispatcher().glBlendFuncSeparateiEXT(buf, srcRGB, dstRGB, srcAlpha, dstAlpha); } GL_APICALL void GL_APIENTRY glColorMaskiEXT(GLuint buf, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { GET_CTX_V2(); SET_ERROR_IF(!ctx->getCaps()->ext_GL_EXT_draw_buffers_indexed, GL_INVALID_OPERATION); ctx->setColorMaski(buf, red, green, blue, alpha); ctx->dispatcher().glColorMaskiEXT(buf, red, green, blue, alpha); } GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT(GLenum cap, GLuint index) { GET_CTX_RET(GL_FALSE); return ctx->dispatcher().glIsEnablediEXT(cap, index); }