1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/GLBlitHelper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,608 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "GLBlitHelper.h" 1.11 +#include "GLContext.h" 1.12 +#include "ScopedGLHelpers.h" 1.13 +#include "mozilla/Preferences.h" 1.14 + 1.15 +namespace mozilla { 1.16 +namespace gl { 1.17 + 1.18 +static void 1.19 +RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples, 1.20 + GLenum aInternalFormat, const gfx::IntSize& aSize) 1.21 +{ 1.22 + if (aSamples) { 1.23 + aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, 1.24 + aSamples, 1.25 + aInternalFormat, 1.26 + aSize.width, aSize.height); 1.27 + } else { 1.28 + aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, 1.29 + aInternalFormat, 1.30 + aSize.width, aSize.height); 1.31 + } 1.32 +} 1.33 + 1.34 + 1.35 +GLuint 1.36 +CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat, 1.37 + GLenum aType, const gfx::IntSize& aSize) 1.38 +{ 1.39 + GLuint tex = 0; 1.40 + aGL->fGenTextures(1, &tex); 1.41 + ScopedBindTexture autoTex(aGL, tex); 1.42 + 1.43 + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); 1.44 + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); 1.45 + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); 1.46 + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); 1.47 + 1.48 + aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 1.49 + 0, 1.50 + aInternalFormat, 1.51 + aSize.width, aSize.height, 1.52 + 0, 1.53 + aFormat, 1.54 + aType, 1.55 + nullptr); 1.56 + 1.57 + return tex; 1.58 +} 1.59 + 1.60 + 1.61 +GLuint 1.62 +CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats, 1.63 + const gfx::IntSize& aSize) 1.64 +{ 1.65 + MOZ_ASSERT(aFormats.color_texInternalFormat); 1.66 + MOZ_ASSERT(aFormats.color_texFormat); 1.67 + MOZ_ASSERT(aFormats.color_texType); 1.68 + 1.69 + return CreateTexture(aGL, 1.70 + aFormats.color_texInternalFormat, 1.71 + aFormats.color_texFormat, 1.72 + aFormats.color_texType, 1.73 + aSize); 1.74 +} 1.75 + 1.76 + 1.77 +GLuint 1.78 +CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples, 1.79 + const gfx::IntSize& aSize) 1.80 +{ 1.81 + GLuint rb = 0; 1.82 + aGL->fGenRenderbuffers(1, &rb); 1.83 + ScopedBindRenderbuffer autoRB(aGL, rb); 1.84 + 1.85 + RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize); 1.86 + 1.87 + return rb; 1.88 +} 1.89 + 1.90 + 1.91 +void 1.92 +CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats, 1.93 + const gfx::IntSize& aSize, bool aMultisample, 1.94 + GLuint* aColorMSRB, GLuint* aDepthRB, 1.95 + GLuint* aStencilRB) 1.96 +{ 1.97 + GLsizei samples = aMultisample ? aFormats.samples : 0; 1.98 + if (aColorMSRB) { 1.99 + MOZ_ASSERT(aFormats.samples > 0); 1.100 + MOZ_ASSERT(aFormats.color_rbFormat); 1.101 + 1.102 + *aColorMSRB = CreateRenderbuffer(aGL, aFormats.color_rbFormat, samples, aSize); 1.103 + } 1.104 + 1.105 + if (aDepthRB && 1.106 + aStencilRB && 1.107 + aFormats.depthStencil) 1.108 + { 1.109 + *aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize); 1.110 + *aStencilRB = *aDepthRB; 1.111 + } else { 1.112 + if (aDepthRB) { 1.113 + MOZ_ASSERT(aFormats.depth); 1.114 + 1.115 + *aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize); 1.116 + } 1.117 + 1.118 + if (aStencilRB) { 1.119 + MOZ_ASSERT(aFormats.stencil); 1.120 + 1.121 + *aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize); 1.122 + } 1.123 + } 1.124 +} 1.125 + 1.126 + 1.127 +GLBlitHelper::GLBlitHelper(GLContext* gl) 1.128 + : mGL(gl) 1.129 + , mTexBlit_Buffer(0) 1.130 + , mTexBlit_VertShader(0) 1.131 + , mTex2DBlit_FragShader(0) 1.132 + , mTex2DRectBlit_FragShader(0) 1.133 + , mTex2DBlit_Program(0) 1.134 + , mTex2DRectBlit_Program(0) 1.135 +{ 1.136 +} 1.137 + 1.138 +GLBlitHelper::~GLBlitHelper() 1.139 +{ 1.140 + DeleteTexBlitProgram(); 1.141 +} 1.142 + 1.143 +// Allowed to be destructive of state we restore in functions below. 1.144 +bool 1.145 +GLBlitHelper::InitTexQuadProgram(GLenum target) 1.146 +{ 1.147 + const char kTexBlit_VertShaderSource[] = "\ 1.148 + attribute vec2 aPosition; \n\ 1.149 + \n\ 1.150 + varying vec2 vTexCoord; \n\ 1.151 + \n\ 1.152 + void main(void) { \n\ 1.153 + vTexCoord = aPosition; \n\ 1.154 + vec2 vertPos = aPosition * 2.0 - 1.0; \n\ 1.155 + gl_Position = vec4(vertPos, 0.0, 1.0); \n\ 1.156 + } \n\ 1.157 + "; 1.158 + 1.159 + const char kTex2DBlit_FragShaderSource[] = "\ 1.160 + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ 1.161 + precision highp float; \n\ 1.162 + #else \n\ 1.163 + precision mediump float; \n\ 1.164 + #endif \n\ 1.165 + \n\ 1.166 + uniform sampler2D uTexUnit; \n\ 1.167 + \n\ 1.168 + varying vec2 vTexCoord; \n\ 1.169 + \n\ 1.170 + void main(void) { \n\ 1.171 + gl_FragColor = texture2D(uTexUnit, vTexCoord); \n\ 1.172 + } \n\ 1.173 + "; 1.174 + 1.175 + const char kTex2DRectBlit_FragShaderSource[] = "\ 1.176 + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ 1.177 + precision highp float; \n\ 1.178 + #else \n\ 1.179 + precision mediump float; \n\ 1.180 + #endif \n\ 1.181 + \n\ 1.182 + uniform sampler2D uTexUnit; \n\ 1.183 + uniform vec2 uTexCoordMult; \n\ 1.184 + \n\ 1.185 + varying vec2 vTexCoord; \n\ 1.186 + \n\ 1.187 + void main(void) { \n\ 1.188 + gl_FragColor = texture2DRect(uTexUnit, \n\ 1.189 + vTexCoord * uTexCoordMult); \n\ 1.190 + } \n\ 1.191 + "; 1.192 + 1.193 + MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || 1.194 + target == LOCAL_GL_TEXTURE_RECTANGLE_ARB); 1.195 + bool success = false; 1.196 + 1.197 + GLuint *programPtr; 1.198 + GLuint *fragShaderPtr; 1.199 + const char* fragShaderSource; 1.200 + if (target == LOCAL_GL_TEXTURE_2D) { 1.201 + programPtr = &mTex2DBlit_Program; 1.202 + fragShaderPtr = &mTex2DBlit_FragShader; 1.203 + fragShaderSource = kTex2DBlit_FragShaderSource; 1.204 + } else { 1.205 + programPtr = &mTex2DRectBlit_Program; 1.206 + fragShaderPtr = &mTex2DRectBlit_FragShader; 1.207 + fragShaderSource = kTex2DRectBlit_FragShaderSource; 1.208 + } 1.209 + 1.210 + GLuint& program = *programPtr; 1.211 + GLuint& fragShader = *fragShaderPtr; 1.212 + 1.213 + // Use do-while(false) to let us break on failure 1.214 + do { 1.215 + if (program) { 1.216 + // Already have it... 1.217 + success = true; 1.218 + break; 1.219 + } 1.220 + 1.221 + if (!mTexBlit_Buffer) { 1.222 + 1.223 + /* CCW tri-strip: 1.224 + * 2---3 1.225 + * | \ | 1.226 + * 0---1 1.227 + */ 1.228 + GLfloat verts[] = { 1.229 + 0.0f, 0.0f, 1.230 + 1.0f, 0.0f, 1.231 + 0.0f, 1.0f, 1.232 + 1.0f, 1.0f 1.233 + }; 1.234 + 1.235 + MOZ_ASSERT(!mTexBlit_Buffer); 1.236 + mGL->fGenBuffers(1, &mTexBlit_Buffer); 1.237 + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer); 1.238 + 1.239 + const size_t vertsSize = sizeof(verts); 1.240 + // Make sure we have a sane size. 1.241 + MOZ_ASSERT(vertsSize >= 3 * sizeof(GLfloat)); 1.242 + mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, vertsSize, verts, LOCAL_GL_STATIC_DRAW); 1.243 + } 1.244 + 1.245 + if (!mTexBlit_VertShader) { 1.246 + 1.247 + const char* vertShaderSource = kTexBlit_VertShaderSource; 1.248 + 1.249 + mTexBlit_VertShader = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER); 1.250 + mGL->fShaderSource(mTexBlit_VertShader, 1, &vertShaderSource, nullptr); 1.251 + mGL->fCompileShader(mTexBlit_VertShader); 1.252 + } 1.253 + 1.254 + MOZ_ASSERT(!fragShader); 1.255 + fragShader = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER); 1.256 + mGL->fShaderSource(fragShader, 1, &fragShaderSource, nullptr); 1.257 + mGL->fCompileShader(fragShader); 1.258 + 1.259 + program = mGL->fCreateProgram(); 1.260 + mGL->fAttachShader(program, mTexBlit_VertShader); 1.261 + mGL->fAttachShader(program, fragShader); 1.262 + mGL->fBindAttribLocation(program, 0, "aPosition"); 1.263 + mGL->fLinkProgram(program); 1.264 + 1.265 + if (mGL->DebugMode()) { 1.266 + GLint status = 0; 1.267 + mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_COMPILE_STATUS, &status); 1.268 + if (status != LOCAL_GL_TRUE) { 1.269 + NS_ERROR("Vert shader compilation failed."); 1.270 + 1.271 + GLint length = 0; 1.272 + mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_INFO_LOG_LENGTH, &length); 1.273 + if (!length) { 1.274 + printf_stderr("No shader info log available.\n"); 1.275 + break; 1.276 + } 1.277 + 1.278 + nsAutoArrayPtr<char> buffer(new char[length]); 1.279 + mGL->fGetShaderInfoLog(mTexBlit_VertShader, length, nullptr, buffer); 1.280 + 1.281 + printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get()); 1.282 + break; 1.283 + } 1.284 + 1.285 + status = 0; 1.286 + mGL->fGetShaderiv(fragShader, LOCAL_GL_COMPILE_STATUS, &status); 1.287 + if (status != LOCAL_GL_TRUE) { 1.288 + NS_ERROR("Frag shader compilation failed."); 1.289 + 1.290 + GLint length = 0; 1.291 + mGL->fGetShaderiv(fragShader, LOCAL_GL_INFO_LOG_LENGTH, &length); 1.292 + if (!length) { 1.293 + printf_stderr("No shader info log available.\n"); 1.294 + break; 1.295 + } 1.296 + 1.297 + nsAutoArrayPtr<char> buffer(new char[length]); 1.298 + mGL->fGetShaderInfoLog(fragShader, length, nullptr, buffer); 1.299 + 1.300 + printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get()); 1.301 + break; 1.302 + } 1.303 + } 1.304 + 1.305 + GLint status = 0; 1.306 + mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &status); 1.307 + if (status != LOCAL_GL_TRUE) { 1.308 + if (mGL->DebugMode()) { 1.309 + NS_ERROR("Linking blit program failed."); 1.310 + GLint length = 0; 1.311 + mGL->fGetProgramiv(program, LOCAL_GL_INFO_LOG_LENGTH, &length); 1.312 + if (!length) { 1.313 + printf_stderr("No program info log available.\n"); 1.314 + break; 1.315 + } 1.316 + 1.317 + nsAutoArrayPtr<char> buffer(new char[length]); 1.318 + mGL->fGetProgramInfoLog(program, length, nullptr, buffer); 1.319 + 1.320 + printf_stderr("Program info log (%d bytes): %s\n", length, buffer.get()); 1.321 + } 1.322 + break; 1.323 + } 1.324 + 1.325 + MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0); 1.326 + GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit"); 1.327 + MOZ_ASSERT(texUnitLoc != -1, "uniform not found"); 1.328 + 1.329 + // Set uniforms here: 1.330 + mGL->fUseProgram(program); 1.331 + mGL->fUniform1i(texUnitLoc, 0); 1.332 + 1.333 + success = true; 1.334 + } while (false); 1.335 + 1.336 + if (!success) { 1.337 + NS_ERROR("Creating program for texture blit failed!"); 1.338 + 1.339 + // Clean up: 1.340 + DeleteTexBlitProgram(); 1.341 + return false; 1.342 + } 1.343 + 1.344 + mGL->fUseProgram(program); 1.345 + mGL->fEnableVertexAttribArray(0); 1.346 + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer); 1.347 + mGL->fVertexAttribPointer(0, 1.348 + 2, 1.349 + LOCAL_GL_FLOAT, 1.350 + false, 1.351 + 0, 1.352 + nullptr); 1.353 + return true; 1.354 +} 1.355 + 1.356 +bool 1.357 +GLBlitHelper::UseTexQuadProgram(GLenum target, const gfx::IntSize& srcSize) 1.358 +{ 1.359 + if (!InitTexQuadProgram(target)) { 1.360 + return false; 1.361 + } 1.362 + 1.363 + if (target == LOCAL_GL_TEXTURE_RECTANGLE_ARB) { 1.364 + GLint texCoordMultLoc = mGL->fGetUniformLocation(mTex2DRectBlit_Program, "uTexCoordMult"); 1.365 + MOZ_ASSERT(texCoordMultLoc != -1, "uniform not found"); 1.366 + mGL->fUniform2f(texCoordMultLoc, srcSize.width, srcSize.height); 1.367 + } 1.368 + 1.369 + return true; 1.370 +} 1.371 + 1.372 +void 1.373 +GLBlitHelper::DeleteTexBlitProgram() 1.374 +{ 1.375 + if (mTexBlit_Buffer) { 1.376 + mGL->fDeleteBuffers(1, &mTexBlit_Buffer); 1.377 + mTexBlit_Buffer = 0; 1.378 + } 1.379 + if (mTexBlit_VertShader) { 1.380 + mGL->fDeleteShader(mTexBlit_VertShader); 1.381 + mTexBlit_VertShader = 0; 1.382 + } 1.383 + if (mTex2DBlit_FragShader) { 1.384 + mGL->fDeleteShader(mTex2DBlit_FragShader); 1.385 + mTex2DBlit_FragShader = 0; 1.386 + } 1.387 + if (mTex2DRectBlit_FragShader) { 1.388 + mGL->fDeleteShader(mTex2DRectBlit_FragShader); 1.389 + mTex2DRectBlit_FragShader = 0; 1.390 + } 1.391 + if (mTex2DBlit_Program) { 1.392 + mGL->fDeleteProgram(mTex2DBlit_Program); 1.393 + mTex2DBlit_Program = 0; 1.394 + } 1.395 + if (mTex2DRectBlit_Program) { 1.396 + mGL->fDeleteProgram(mTex2DRectBlit_Program); 1.397 + mTex2DRectBlit_Program = 0; 1.398 + } 1.399 +} 1.400 + 1.401 +void 1.402 +GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, 1.403 + const gfx::IntSize& srcSize, 1.404 + const gfx::IntSize& destSize) 1.405 +{ 1.406 + MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB)); 1.407 + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); 1.408 + 1.409 + MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); 1.410 + 1.411 + ScopedBindFramebuffer boundFB(mGL); 1.412 + ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); 1.413 + 1.414 + mGL->BindReadFB(srcFB); 1.415 + mGL->BindDrawFB(destFB); 1.416 + 1.417 + mGL->fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, 1.418 + 0, 0, destSize.width, destSize.height, 1.419 + LOCAL_GL_COLOR_BUFFER_BIT, 1.420 + LOCAL_GL_NEAREST); 1.421 +} 1.422 + 1.423 +void 1.424 +GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, 1.425 + const gfx::IntSize& srcSize, 1.426 + const gfx::IntSize& destSize, 1.427 + const GLFormats& srcFormats) 1.428 +{ 1.429 + MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB)); 1.430 + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); 1.431 + 1.432 + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { 1.433 + BlitFramebufferToFramebuffer(srcFB, destFB, 1.434 + srcSize, destSize); 1.435 + return; 1.436 + } 1.437 + 1.438 + GLuint tex = CreateTextureForOffscreen(mGL, srcFormats, srcSize); 1.439 + MOZ_ASSERT(tex); 1.440 + 1.441 + BlitFramebufferToTexture(srcFB, tex, srcSize, srcSize); 1.442 + BlitTextureToFramebuffer(tex, destFB, srcSize, destSize); 1.443 + 1.444 + mGL->fDeleteTextures(1, &tex); 1.445 +} 1.446 + 1.447 +void 1.448 +GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, 1.449 + const gfx::IntSize& srcSize, 1.450 + const gfx::IntSize& destSize, 1.451 + GLenum srcTarget) 1.452 +{ 1.453 + MOZ_ASSERT(mGL->fIsTexture(srcTex)); 1.454 + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); 1.455 + 1.456 + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { 1.457 + ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget); 1.458 + MOZ_ASSERT(srcWrapper.IsComplete()); 1.459 + 1.460 + BlitFramebufferToFramebuffer(srcWrapper.FB(), destFB, 1.461 + srcSize, destSize); 1.462 + return; 1.463 + } 1.464 + 1.465 + 1.466 + ScopedBindFramebuffer boundFB(mGL, destFB); 1.467 + // UseTexQuadProgram initializes a shader that reads 1.468 + // from texture unit 0. 1.469 + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); 1.470 + ScopedBindTexture boundTex(mGL, srcTex, srcTarget); 1.471 + 1.472 + GLuint boundProgram = 0; 1.473 + mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &boundProgram); 1.474 + 1.475 + GLuint boundBuffer = 0; 1.476 + mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &boundBuffer); 1.477 + 1.478 + /* 1.479 + * mGL->fGetVertexAttribiv takes: 1.480 + * VERTEX_ATTRIB_ARRAY_ENABLED 1.481 + * VERTEX_ATTRIB_ARRAY_SIZE, 1.482 + * VERTEX_ATTRIB_ARRAY_STRIDE, 1.483 + * VERTEX_ATTRIB_ARRAY_TYPE, 1.484 + * VERTEX_ATTRIB_ARRAY_NORMALIZED, 1.485 + * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 1.486 + * CURRENT_VERTEX_ATTRIB 1.487 + * 1.488 + * CURRENT_VERTEX_ATTRIB is vertex shader state. \o/ 1.489 + * Others appear to be vertex array state, 1.490 + * or alternatively in the internal vertex array state 1.491 + * for a buffer object. 1.492 + */ 1.493 + 1.494 + GLint attrib0_enabled = 0; 1.495 + GLint attrib0_size = 0; 1.496 + GLint attrib0_stride = 0; 1.497 + GLint attrib0_type = 0; 1.498 + GLint attrib0_normalized = 0; 1.499 + GLint attrib0_bufferBinding = 0; 1.500 + void* attrib0_pointer = nullptr; 1.501 + 1.502 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib0_enabled); 1.503 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib0_size); 1.504 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib0_stride); 1.505 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib0_type); 1.506 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib0_normalized); 1.507 + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &attrib0_bufferBinding); 1.508 + mGL->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib0_pointer); 1.509 + // Note that uniform values are program state, so we don't need to rebind those. 1.510 + 1.511 + ScopedGLState blend (mGL, LOCAL_GL_BLEND, false); 1.512 + ScopedGLState cullFace (mGL, LOCAL_GL_CULL_FACE, false); 1.513 + ScopedGLState depthTest (mGL, LOCAL_GL_DEPTH_TEST, false); 1.514 + ScopedGLState dither (mGL, LOCAL_GL_DITHER, false); 1.515 + ScopedGLState polyOffsFill(mGL, LOCAL_GL_POLYGON_OFFSET_FILL, false); 1.516 + ScopedGLState sampleAToC (mGL, LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false); 1.517 + ScopedGLState sampleCover (mGL, LOCAL_GL_SAMPLE_COVERAGE, false); 1.518 + ScopedGLState scissor (mGL, LOCAL_GL_SCISSOR_TEST, false); 1.519 + ScopedGLState stencil (mGL, LOCAL_GL_STENCIL_TEST, false); 1.520 + 1.521 + realGLboolean colorMask[4]; 1.522 + mGL->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorMask); 1.523 + mGL->fColorMask(LOCAL_GL_TRUE, 1.524 + LOCAL_GL_TRUE, 1.525 + LOCAL_GL_TRUE, 1.526 + LOCAL_GL_TRUE); 1.527 + 1.528 + GLint viewport[4]; 1.529 + mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport); 1.530 + mGL->fViewport(0, 0, destSize.width, destSize.height); 1.531 + 1.532 + // Does destructive things to (only!) what we just saved above. 1.533 + bool good = UseTexQuadProgram(srcTarget, srcSize); 1.534 + if (!good) { 1.535 + // We're up against the wall, so bail. 1.536 + // This should really be MOZ_CRASH(why) or MOZ_RUNTIME_ASSERT(good). 1.537 + printf_stderr("[%s:%d] Fatal Error: Failed to prepare to blit texture->framebuffer.\n", 1.538 + __FILE__, __LINE__); 1.539 + MOZ_CRASH(); 1.540 + } 1.541 + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); 1.542 + 1.543 + mGL->fViewport(viewport[0], viewport[1], 1.544 + viewport[2], viewport[3]); 1.545 + 1.546 + mGL->fColorMask(colorMask[0], 1.547 + colorMask[1], 1.548 + colorMask[2], 1.549 + colorMask[3]); 1.550 + 1.551 + if (attrib0_enabled) 1.552 + mGL->fEnableVertexAttribArray(0); 1.553 + 1.554 + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0_bufferBinding); 1.555 + mGL->fVertexAttribPointer(0, 1.556 + attrib0_size, 1.557 + attrib0_type, 1.558 + attrib0_normalized, 1.559 + attrib0_stride, 1.560 + attrib0_pointer); 1.561 + 1.562 + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, boundBuffer); 1.563 + 1.564 + mGL->fUseProgram(boundProgram); 1.565 +} 1.566 + 1.567 +void 1.568 +GLBlitHelper::BlitFramebufferToTexture(GLuint srcFB, GLuint destTex, 1.569 + const gfx::IntSize& srcSize, 1.570 + const gfx::IntSize& destSize, 1.571 + GLenum destTarget) 1.572 +{ 1.573 + MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB)); 1.574 + MOZ_ASSERT(mGL->fIsTexture(destTex)); 1.575 + 1.576 + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { 1.577 + ScopedFramebufferForTexture destWrapper(mGL, destTex, destTarget); 1.578 + 1.579 + BlitFramebufferToFramebuffer(srcFB, destWrapper.FB(), 1.580 + srcSize, destSize); 1.581 + return; 1.582 + } 1.583 + 1.584 + ScopedBindTexture autoTex(mGL, destTex, destTarget); 1.585 + ScopedBindFramebuffer boundFB(mGL, srcFB); 1.586 + ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); 1.587 + 1.588 + mGL->fCopyTexSubImage2D(destTarget, 0, 1.589 + 0, 0, 1.590 + 0, 0, 1.591 + srcSize.width, srcSize.height); 1.592 +} 1.593 + 1.594 +void 1.595 +GLBlitHelper::BlitTextureToTexture(GLuint srcTex, GLuint destTex, 1.596 + const gfx::IntSize& srcSize, 1.597 + const gfx::IntSize& destSize, 1.598 + GLenum srcTarget, GLenum destTarget) 1.599 +{ 1.600 + MOZ_ASSERT(mGL->fIsTexture(srcTex)); 1.601 + MOZ_ASSERT(mGL->fIsTexture(destTex)); 1.602 + 1.603 + // Generally, just use the CopyTexSubImage path 1.604 + ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget); 1.605 + 1.606 + BlitFramebufferToTexture(srcWrapper.FB(), destTex, 1.607 + srcSize, destSize, destTarget); 1.608 +} 1.609 + 1.610 +} 1.611 +}