--- src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm.orig +++ src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm @@ -43,6 +43,7 @@ const rx::FunctionsGL *mFunctions; GLuint mReadFramebuffer; + GLuint mPresentProgram; } - (id)initWithSharedState:(rx::SharedSwapState *)swapState withContext:(CGLContextObj)displayContext @@ -136,19 +137,73 @@ [self setNeedsDisplay]; } - // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the - // GL_DRAW_FRAMEBUFFER_BINDING query - GLint drawFBO; - mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO); - - mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer); - mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - texture.texture, 0); - - mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer); - mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); - mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width, - texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + if (mFunctions->blitFramebuffer != nullptr) + { + GLint drawFBO; + mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO); + + mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer); + mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + texture.texture, 0); + + mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer); + mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO); + mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width, + texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else + { + // GL 2.x without GL_EXT_framebuffer_blit (e.g. Mac OS X 10.6): draw the presented + // texture with a minimal GLSL 1.10 program instead. This context is private to the + // layer, so state set here cannot interfere with ANGLE's state tracking. + if (mPresentProgram == 0) + { + const char *vsSource = + "attribute vec2 pos;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(pos, 0.0, 1.0);\n" + " texcoord = pos * 0.5 + 0.5;\n" + "}\n"; + const char *fsSource = + "varying vec2 texcoord;\n" + "uniform sampler2D tex;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(tex, texcoord);\n" + "}\n"; + + GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER); + mFunctions->shaderSource(vs, 1, &vsSource, nullptr); + mFunctions->compileShader(vs); + + GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER); + mFunctions->shaderSource(fs, 1, &fsSource, nullptr); + mFunctions->compileShader(fs); + + mPresentProgram = mFunctions->createProgram(); + mFunctions->attachShader(mPresentProgram, vs); + mFunctions->attachShader(mPresentProgram, fs); + mFunctions->bindAttribLocation(mPresentProgram, 0, "pos"); + mFunctions->linkProgram(mPresentProgram); + mFunctions->deleteShader(vs); + mFunctions->deleteShader(fs); + + mFunctions->useProgram(mPresentProgram); + mFunctions->uniform1i(mFunctions->getUniformLocation(mPresentProgram, "tex"), 0); + } + + static const GLfloat kQuad[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f}; + + mFunctions->activeTexture(GL_TEXTURE0); + mFunctions->bindTexture(GL_TEXTURE_2D, texture.texture); + mFunctions->useProgram(mPresentProgram); + mFunctions->bindBuffer(GL_ARRAY_BUFFER, 0); + mFunctions->vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kQuad); + mFunctions->enableVertexAttribArray(0); + mFunctions->drawArrays(GL_TRIANGLE_STRIP, 0, 4); + } // Call the super method to flush the context [super drawInCGLContext:glContext @@ -232,6 +287,10 @@ ANGLE_UNSAFE_TODO(mSwapState.textures[i].texture)); mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + // The layer's no-blit present path samples these textures; without filters set they + // are incomplete (default MIN_FILTER requires mipmaps). + mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ANGLE_UNSAFE_TODO(mSwapState.textures[i].width) = width; ANGLE_UNSAFE_TODO(mSwapState.textures[i].height) = height; ANGLE_UNSAFE_TODO(mSwapState.textures[i].swapId) = 0; @@ -246,8 +305,6 @@ [mLayer addSublayer:mSwapLayer]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 [mSwapLayer setContentsScale:[mLayer contentsScale]]; -#else - [mSwapLayer setContentsScale:1.0]; #endif mFunctions->genRenderbuffers(1, &mDSRenderbuffer);