| 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 texture_uniform = |
| 98 glGetUniformLocation(blit_program_, "u_source_texture"); |
| 99 glUseProgram(blit_program_); |
| 100 glUniform1i(texture_uniform, 0); |
| 101 |
| 102 glGenTextures(scratch_textures_.size(), scratch_textures_.data()); |
| 103 glActiveTexture(GL_TEXTURE0); |
| 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 blit_program_ = 0; |
| 129 |
| 130 glDeleteTextures(scratch_textures_.size(), scratch_textures_.data()); |
| 131 scratch_textures_.fill(0); |
| 132 |
| 133 glDeleteFramebuffersEXT(1, &scratch_fbo_); |
| 134 scratch_fbo_ = 0; |
| 135 |
| 136 glDeleteVertexArraysOES(1, &vao_); |
| 137 vao_ = 0; |
| 138 |
| 139 initialized_ = false; |
| 140 } |
| 141 |
| 142 void CopyTexImageResourceManager::DoCopyTexImage2DToLUMAComatabilityTexture( |
| 143 const gles2::GLES2Decoder* decoder, |
| 144 GLuint dest_texture, |
| 145 GLenum dest_texture_target, |
| 146 GLenum dest_target, |
| 147 GLenum luma_format, |
| 148 GLenum luma_type, |
| 149 GLint level, |
| 150 GLenum internal_format, |
| 151 GLint x, |
| 152 GLint y, |
| 153 GLsizei width, |
| 154 GLsizei height, |
| 155 GLuint source_framebuffer, |
| 156 GLenum source_framebuffer_internal_format) { |
| 157 GLenum adjusted_internal_format = |
| 158 gles2::TextureManager::AdjustTexInternalFormat(feature_info_.get(), |
| 159 internal_format); |
| 160 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); |
| 161 GLenum adjusted_format = gles2::TextureManager::AdjustTexFormat( |
| 162 feature_info_.get(), internal_format); |
| 163 glTexImage2D(dest_target, level, adjusted_internal_format, width, height, 0, |
| 164 adjusted_format, luma_type, nullptr); |
| 165 DoCopyTexSubImage2DToLUMAComatabilityTexture( |
| 166 decoder, dest_texture, dest_texture_target, dest_target, luma_format, |
| 167 luma_type, level, 0, 0, x, y, width, height, source_framebuffer, |
| 168 source_framebuffer_internal_format); |
| 169 } |
| 170 |
| 171 void CopyTexImageResourceManager::DoCopyTexSubImage2DToLUMAComatabilityTexture( |
| 172 const gles2::GLES2Decoder* decoder, |
| 173 GLuint dest_texture, |
| 174 GLenum dest_texture_target, |
| 175 GLenum dest_target, |
| 176 GLenum luma_format, |
| 177 GLenum luma_type, |
| 178 GLint level, |
| 179 GLint xoffset, |
| 180 GLint yoffset, |
| 181 GLint x, |
| 182 GLint y, |
| 183 GLsizei width, |
| 184 GLsizei height, |
| 185 GLuint source_framebuffer, |
| 186 GLenum source_framebuffer_internal_format) { |
| 187 DCHECK(initialized_); |
| 188 |
| 189 // Copy the framebuffer to the first scratch texture |
| 190 // TODO(geofflang): This could be optimized further by detecting if the source |
| 191 // framebuffer is copying from a texture and sample directly from that texture |
| 192 // instead of doing an extra copy |
| 193 |
| 194 glBindFramebufferEXT(GL_FRAMEBUFFER, source_framebuffer); |
| 195 glActiveTexture(GL_TEXTURE0); |
| 196 glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]); |
| 197 glCopyTexImage2D(GL_TEXTURE_2D, 0, source_framebuffer_internal_format, x, y, |
| 198 width, height, 0); |
| 199 |
| 200 // Set the swizzle of the scratch texture so that the channels sample into the |
| 201 // correct emulated LUMA channels. |
| 202 GLint swizzle[4] = { |
| 203 (luma_format == GL_ALPHA) ? GL_ALPHA : GL_RED, |
| 204 (luma_format == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, |
| 205 GL_ZERO, |
| 206 }; |
| 207 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); |
| 208 |
| 209 // Make a temporary framebuffer using the second scratch texture to render the |
| 210 // swizzled result to. |
| 211 // TODO(geofflang): Could be optimized more by rendering directly to the |
| 212 // destination texture but this isn't always possible because the destination |
| 213 // may be an incomplete cube map |
| 214 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); |
| 215 GLenum compatability_format = |
| 216 gles2::TextureManager::AdjustTexFormat(feature_info_.get(), luma_format); |
| 217 glBindTexture(GL_TEXTURE_2D, scratch_textures_[1]); |
| 218 glTexImage2D(GL_TEXTURE_2D, 0, compatability_format, width, height, 0, |
| 219 compatability_format, luma_type, nullptr); |
| 220 |
| 221 glBindFramebufferEXT(GL_FRAMEBUFFER, scratch_fbo_); |
| 222 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |
| 223 scratch_textures_[1], 0); |
| 224 |
| 225 // Render to the destination texture, sampling from the scratch texture |
| 226 glUseProgram(blit_program_); |
| 227 glViewport(0, 0, width, height); |
| 228 glDisable(GL_SCISSOR_TEST); |
| 229 glDisable(GL_DEPTH_TEST); |
| 230 glDisable(GL_STENCIL_TEST); |
| 231 glDisable(GL_CULL_FACE); |
| 232 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| 233 glDepthMask(GL_FALSE); |
| 234 glDisable(GL_BLEND); |
| 235 glDisable(GL_DITHER); |
| 236 |
| 237 glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]); |
| 238 glBindVertexArrayOES(vao_); |
| 239 |
| 240 glDrawArrays(GL_TRIANGLES, 0, 6); |
| 241 |
| 242 // Finally, copy the swizzled texture to the destination texture |
| 243 glBindTexture(dest_texture_target, dest_texture); |
| 244 glCopyTexSubImage2D(dest_target, level, xoffset, yoffset, 0, 0, width, |
| 245 height); |
| 246 |
| 247 // Restore state |
| 248 decoder->RestoreAllAttributes(); |
| 249 decoder->RestoreTextureUnitBindings(0); |
| 250 decoder->RestoreActiveTexture(); |
| 251 decoder->RestoreProgramBindings(); |
| 252 decoder->RestoreBufferBindings(); |
| 253 decoder->RestoreFramebufferBindings(); |
| 254 decoder->RestoreGlobalState(); |
| 255 } |
| 256 |
| 257 // static |
| 258 bool CopyTexImageResourceManager::CopyTexImageRequiresBlit( |
| 259 const gles2::FeatureInfo* feature_info, |
| 260 GLenum dest_texture_format) { |
| 261 if (feature_info->gl_version_info().is_desktop_core_profile) { |
| 262 switch (dest_texture_format) { |
| 263 case GL_LUMINANCE: |
| 264 case GL_ALPHA: |
| 265 case GL_LUMINANCE_ALPHA: |
| 266 return true; |
| 267 } |
| 268 } |
| 269 |
| 270 return false; |
| 271 } |
| 272 |
| 273 } // namespace gpu |
| OLD | NEW |