Opengl 一些问题解答
为什么opengl 不能跨线程
大家有没有想过这个问题,网上给出的答案其实看得不太明白,接下来我们看源码让你知道
C EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) {
const egl::Config *config = mConfigSet.get(configHandle); gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess); return context; } gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) {
return new gl::Context(config, shareContext, notifyResets, robustAccess); }
EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
... glMakeCurrent(context, display, static_cast<egl::Surface*>(draw)); } void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface) {
gl::makeCurrent(context, display, surface); } void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) {
Current *current = (Current*)TlsGetValue(currentTLS);
current->context = context; current->display = display; } |
通过上边源码可以看到, 它是把context 放入到thread local中去,这就是不能夸线程根本原因,在做opengl 一些操作的时候,首先去线程中取context, 如果夸了线程取的context就不是之前使用的context导致了crash,这个希望大家要明确知道
纹理是什么
C++ glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
glGenTextures(GLsizei n, GLuint* textures)
这个textures返回的 是int值,具体是什么?
要想知道这个答案要看下opengles的源码:
C void __stdcall glGenTextures(GLsizei n, GLuint* textures) {
gl::Context *context = gl::getNonLostContext(); for (int i = 0; i < n; i++) {
textures[i] = context->createTexture(); } } GLuint Context::createTexture() {
return mResourceManager->createTexture(); } GLuint ResourceManager::createTexture() {
GLuint handle = mTextureHandleAllocator.allocate(); mTextureMap[handle] = NULL; return handle; } GLuint HandleAllocator::allocate() {
/* typedef std::vector<GLuint> HandleList; HandleList mFreeValues; */ if (mFreeValues.size()) {
GLuint handle = mFreeValues.back(); mFreeValues.pop_back(); return handle; } return mNextValue++; } |
通过上边源码也可以看出来, 首先创建纹理的时候会从当前线程的threadlocal取出context,再从context取出来mResourceManager,在从mResourcManager取出一个空隙的ID,也就说这个gentexutre只是拿到一个id,其他什么都没干
纹理绑定到底干了些啥
C void __stdcall glBindTexture(GLenum target, GLuint texture) {
EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); gl::Context *context = gl::getNonLostContext(); gl::Texture *textureObject = context->getTexture(texture); switch (target) {
case GL_TEXTURE_2D: context->bindTexture2D(texture); return; } } Texture *Context::getTexture(GLuint handle) {
return mResourceManager->getTexture(handle); } Texture *ResourceManager::getTexture(unsigned int handle) {
if (handle == 0) return NULL; TextureMap::iterator texture = mTextureMap.find(handle); if (texture == mTextureMap.end()) {
return NULL; } else {
return texture->second; } } void Context::bindTexture2D(GLuint texture) {
mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); // BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; |