Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" | |
| 6 | |
| 7 #include "gpu/command_buffer/service/texture_manager.h" | |
| 8 #include "ui/gl/gl_version_info.h" | |
| 9 | |
| 10 namespace { | |
| 11 | |
| 12 void CompileShader(GLuint shader, const char* shader_source) { | |
| 13 glShaderSource(shader, 1, &shader_source, 0); | |
| 14 glCompileShader(shader); | |
| 15 #ifndef NDEBUG | |
| 16 GLint compile_status; | |
| 17 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | |
| 18 if (GL_TRUE != compile_status) | |
| 19 DLOG(ERROR) << "CopyTexImage: shader compilation failure."; | |
| 20 #endif | |
| 21 } | |
| 22 | |
| 23 } // anonymous namespace | |
| 24 | |
| 25 namespace gpu { | |
| 26 | |
| 27 CopyTexImageResourceManager::CopyTexImageResourceManager( | |
| 28 const gles2::FeatureInfo* feature_info) | |
| 29 : feature_info_(feature_info) { | |
| 30 DCHECK(feature_info->gl_version_info().is_desktop_core_profile); | |
| 31 } | |
| 32 | |
| 33 CopyTexImageResourceManager::~CopyTexImageResourceManager() {} | |
| 34 | |
| 35 void CopyTexImageResourceManager::Initialize( | |
| 36 const gles2::GLES2Decoder* decoder) { | |
| 37 if (initialized_) { | |
| 38 return; | |
| 39 } | |
| 40 | |
| 41 blit_program_ = glCreateProgram(); | |
| 42 | |
| 43 // Compile the fragment shader | |
| 44 const char* vs_source = | |
| 45 "#version 150\n" | |
| 46 "out vec2 v_texcoord;\n" | |
| 47 "\n" | |
| 48 "void main()\n" | |
| 49 "{\n" | |
| 50 " const vec2 quad_positions[6] = vec2[6]\n" | |
| 51 " (\n" | |
| 52 " vec2(0.0f, 0.0f),\n" | |
| 53 " vec2(0.0f, 1.0f),\n" | |
| 54 " vec2(1.0f, 0.0f),\n" | |
| 55 "\n" | |
| 56 " vec2(0.0f, 1.0f),\n" | |
| 57 " vec2(1.0f, 0.0f),\n" | |
| 58 " vec2(1.0f, 1.0f)\n" | |
| 59 " );\n" | |
| 60 "\n" | |
| 61 " gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, " | |
| 62 "1.0);\n" | |
| 63 " v_texcoord = quad_positions[gl_VertexID];\n" | |
| 64 "}\n"; | |
| 65 | |
| 66 GLuint vs = glCreateShader(GL_VERTEX_SHADER); | |
| 67 CompileShader(vs, vs_source); | |
| 68 glAttachShader(blit_program_, vs); | |
| 69 glDeleteShader(vs); | |
| 70 | |
| 71 // Compile the vertex shader | |
| 72 const char* fs_source = | |
| 73 "#version 150\n" | |
| 74 "uniform sampler2D u_source_texture;\n" | |
| 75 "in vec2 v_texcoord;\n" | |
| 76 "out vec4 output_color;\n" | |
| 77 "\n" | |
| 78 "void main()\n" | |
| 79 "{\n" | |
| 80 " output_color = texture(u_source_texture, v_texcoord);\n" | |
| 81 "}\n"; | |
| 82 | |
| 83 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); | |
| 84 CompileShader(fs, fs_source); | |
| 85 glAttachShader(blit_program_, fs); | |
| 86 glDeleteShader(fs); | |
| 87 | |
| 88 glLinkProgram(blit_program_); | |
| 89 #ifndef NDEBUG | |
| 90 GLint linked = 0; | |
| 91 glGetProgramiv(blit_program_, GL_LINK_STATUS, &linked); | |
| 92 if (!linked) { | |
| 93 DLOG(ERROR) << "CopyTexImage: program link failure."; | |
| 94 } | |
| 95 #endif | |
| 96 | |
| 97 GLuint textureUniform = | |
|
Zhenyao Mo
2016/06/01 18:24:18
nit: texture_uniform.
Geoff Lang
2016/06/01 20:12:18
Done.
| |
| 98 glGetUniformLocation(blit_program_, "u_source_texture"); | |
| 99 glUseProgram(blit_program_); | |
| 100 glUniform1i(textureUniform, 0); | |
| 101 | |
| 102 glGenTextures(scratch_textures_.size(), scratch_textures_.data()); | |
| 103 glActiveTexture(GL_TEXTURE0); | |
|
Zhenyao Mo
2016/06/01 18:24:18
You don't care which active texture to use, so no
Zhenyao Mo
2016/06/01 18:26:48
Never mind, it's easier this way for RestoreTextur
| |
| 104 for (auto scratch_texture : scratch_textures_) { | |
| 105 glBindTexture(GL_TEXTURE_2D, scratch_texture); | |
| 106 | |
| 107 // Use nearest, non-mipmapped sampling with the scratch texture | |
| 108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 110 } | |
| 111 | |
| 112 glGenFramebuffersEXT(1, &scratch_fbo_); | |
| 113 glGenVertexArraysOES(1, &vao_); | |
| 114 | |
| 115 decoder->RestoreTextureUnitBindings(0); | |
| 116 decoder->RestoreActiveTexture(); | |
| 117 decoder->RestoreProgramBindings(); | |
| 118 | |
| 119 initialized_ = true; | |
| 120 } | |
| 121 | |
| 122 void CopyTexImageResourceManager::Destroy() { | |
| 123 if (!initialized_) { | |
| 124 return; | |
| 125 } | |
| 126 | |
| 127 glDeleteProgram(blit_program_); | |
| 128 glDeleteTextures(scratch_textures_.size(), scratch_textures_.data()); | |
| 129 glDeleteFramebuffersEXT(1, &scratch_fbo_); | |
| 130 glDeleteVertexArraysOES(1, &vao_); | |
|
Zhenyao Mo
2016/06/01 18:26:48
Although you don't intend it to be re-initialized
Geoff Lang
2016/06/01 20:12:18
Done.
| |
| 131 | |
| 132 initialized_ = false; | |
| 133 } | |
| 134 | |
| 135 void CopyTexImageResourceManager::DoCopyTexImage2DToLUMAComatabilityTexture( | |
| 136 const gles2::GLES2Decoder* decoder, | |
| 137 GLuint dest_texture, | |
| 138 GLenum dest_texture_target, | |
| 139 GLenum dest_target, | |
| 140 GLenum luma_format, | |
| 141 GLenum luma_type, | |
| 142 GLint level, | |
| 143 GLenum internal_format, | |
| 144 GLint x, | |
| 145 GLint y, | |
| 146 GLsizei width, | |
| 147 GLsizei height, | |
| 148 GLuint source_framebuffer, | |
| 149 GLenum source_framebuffer_internal_format) { | |
| 150 GLenum adjusted_internal_format = | |
| 151 gles2::TextureManager::AdjustTexInternalFormat(feature_info_.get(), | |
| 152 internal_format); | |
| 153 GLenum adjusted_format = gles2::TextureManager::AdjustTexFormat( | |
| 154 feature_info_.get(), internal_format); | |
| 155 glTexImage2D(dest_target, level, adjusted_internal_format, width, height, 0, | |
| 156 adjusted_format, luma_type, nullptr); | |
| 157 DoCopyTexSubImage2DToLUMAComatabilityTexture( | |
| 158 decoder, dest_texture, dest_texture_target, dest_target, luma_format, | |
| 159 luma_type, level, 0, 0, x, y, width, height, source_framebuffer, | |
| 160 source_framebuffer_internal_format); | |
| 161 } | |
| 162 | |
| 163 void CopyTexImageResourceManager::DoCopyTexSubImage2DToLUMAComatabilityTexture( | |
| 164 const gles2::GLES2Decoder* decoder, | |
| 165 GLuint dest_texture, | |
| 166 GLenum dest_texture_target, | |
| 167 GLenum dest_target, | |
| 168 GLenum luma_format, | |
| 169 GLenum luma_type, | |
| 170 GLint level, | |
| 171 GLint xoffset, | |
| 172 GLint yoffset, | |
| 173 GLint x, | |
| 174 GLint y, | |
| 175 GLsizei width, | |
| 176 GLsizei height, | |
| 177 GLuint source_framebuffer, | |
| 178 GLenum source_framebuffer_internal_format) { | |
| 179 DCHECK(initialized_); | |
| 180 | |
| 181 // Copy the framebuffer to the first scratch texture | |
| 182 // TODO(geofflang): This could be optimized further by detecting if the source | |
| 183 // framebuffer is copying from a texture and sample directly from that texture | |
| 184 // instead of doing an extra copy | |
| 185 | |
| 186 glBindFramebufferEXT(GL_FRAMEBUFFER, source_framebuffer); | |
| 187 glActiveTexture(GL_TEXTURE0); | |
| 188 glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]); | |
| 189 glCopyTexImage2D(GL_TEXTURE_2D, 0, source_framebuffer_internal_format, x, y, | |
| 190 width, height, 0); | |
| 191 | |
| 192 // Set the swizzle of the scratch texture so that the channels sample into the | |
| 193 // correct emulated LUMA channels. | |
| 194 GLint swizzle[4] = { | |
| 195 (luma_format == GL_ALPHA) ? GL_ALPHA : GL_RED, | |
| 196 (luma_format == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, | |
| 197 GL_ZERO, | |
| 198 }; | |
| 199 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); | |
| 200 | |
| 201 // Make a temporary framebuffer using the second scratch texture to render the | |
| 202 // swizzled result to. | |
| 203 // TODO(geofflang): Could be optimized more by rendering directly to the | |
| 204 // destination texture but this isn't always possible because the destination | |
| 205 // may be an incomplete cube map | |
| 206 GLenum compatability_format = | |
| 207 gles2::TextureManager::AdjustTexFormat(feature_info_.get(), luma_format); | |
| 208 glBindTexture(GL_TEXTURE_2D, scratch_textures_[1]); | |
| 209 glTexImage2D(GL_TEXTURE_2D, 0, compatability_format, width, height, 0, | |
|
Zhenyao Mo
2016/06/01 18:24:18
You will need to glBindBuffer(GL_PIXEL_UNPACK_BUFF
Geoff Lang
2016/06/01 20:12:18
Ah, good point, fixed.
| |
| 210 compatability_format, luma_type, nullptr); | |
| 211 | |
| 212 glBindFramebufferEXT(GL_FRAMEBUFFER, scratch_fbo_); | |
| 213 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
| 214 scratch_textures_[1], 0); | |
| 215 | |
| 216 // Render to the destination texture, sampling from the scratch texture | |
| 217 glUseProgram(blit_program_); | |
| 218 glViewport(0, 0, width, height); | |
| 219 glDisable(GL_SCISSOR_TEST); | |
| 220 glDisable(GL_DEPTH_TEST); | |
| 221 glDisable(GL_STENCIL_TEST); | |
| 222 glDisable(GL_CULL_FACE); | |
|
Zhenyao Mo
2016/06/01 18:24:18
Should we also disable GL_DITHER?
Geoff Lang
2016/06/01 20:12:18
Done.
| |
| 223 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
| 224 glDepthMask(GL_FALSE); | |
| 225 glDisable(GL_BLEND); | |
| 226 glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]); | |
| 227 glBindVertexArrayOES(vao_); | |
| 228 | |
| 229 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 230 | |
| 231 // Finally, copy the swizzled texture to the destination texture | |
| 232 glBindTexture(dest_texture_target, dest_texture); | |
| 233 glCopyTexSubImage2D(dest_target, level, xoffset, yoffset, 0, 0, width, | |
| 234 height); | |
| 235 | |
| 236 // Restore state | |
| 237 decoder->RestoreAllAttributes(); | |
| 238 decoder->RestoreTextureUnitBindings(0); | |
| 239 decoder->RestoreActiveTexture(); | |
| 240 decoder->RestoreProgramBindings(); | |
| 241 decoder->RestoreBufferBindings(); | |
| 242 decoder->RestoreFramebufferBindings(); | |
| 243 decoder->RestoreGlobalState(); | |
| 244 } | |
| 245 | |
| 246 // static | |
| 247 bool CopyTexImageResourceManager::CopyTexImageRequiresBlit( | |
| 248 const gles2::FeatureInfo* feature_info, | |
| 249 GLenum dest_texture_format) { | |
| 250 if (feature_info->gl_version_info().is_desktop_core_profile) { | |
| 251 switch (dest_texture_format) { | |
| 252 case GL_LUMINANCE: | |
| 253 case GL_ALPHA: | |
| 254 case GL_LUMINANCE_ALPHA: | |
| 255 return true; | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 return false; | |
| 260 } | |
| 261 | |
| 262 } // namespace gpu | |
| OLD | NEW |