Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "gpu/command_buffer/service/gl_utils.h" | 11 #include "gpu/command_buffer/service/gl_utils.h" |
| 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 13 #include "ui/gl/gl_implementation.h" | 13 #include "ui/gl/gl_implementation.h" |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, | 17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, |
| 18 0.0f, 1.0f, 0.0f, 0.0f, | 18 0.0f, 1.0f, 0.0f, 0.0f, |
| 19 0.0f, 0.0f, 1.0f, 0.0f, | 19 0.0f, 0.0f, 1.0f, 0.0f, |
| 20 0.0f, 0.0f, 0.0f, 1.0f}; | 20 0.0f, 0.0f, 0.0f, 1.0f}; |
| 21 | 21 |
| 22 enum VertexShaderId { | |
| 23 VERTEX_SHADER_COPY_TEXTURE, | |
| 24 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, | |
| 25 NUM_VERTEX_SHADERS, | |
| 26 }; | |
| 27 | |
| 28 enum FragmentShaderId { | 22 enum FragmentShaderId { |
| 29 FRAGMENT_SHADER_COPY_TEXTURE_2D, | 23 FRAGMENT_SHADER_COPY_TEXTURE_2D, |
| 30 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, | 24 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
| 31 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, | 25 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
| 32 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, | 26 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, |
| 33 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, | 27 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, |
| 34 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, | 28 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, |
| 35 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, | 29 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, |
| 36 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, | 30 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, |
| 37 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, | 31 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, |
| 38 NUM_FRAGMENT_SHADERS, | 32 NUM_FRAGMENT_SHADERS, |
| 39 }; | 33 }; |
| 40 | 34 |
| 41 // Returns the correct vertex shader id to evaluate the copy operation for | |
| 42 // the CHROMIUM_flipy setting. | |
| 43 VertexShaderId GetVertexShaderId(bool flip_y) { | |
| 44 // bit 0: flip y | |
| 45 static VertexShaderId shader_ids[] = { | |
| 46 VERTEX_SHADER_COPY_TEXTURE, | |
| 47 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, | |
| 48 }; | |
| 49 | |
| 50 unsigned index = flip_y ? 1 : 0; | |
| 51 return shader_ids[index]; | |
| 52 } | |
| 53 | |
| 54 // Returns the correct fragment shader id to evaluate the copy operation for | 35 // Returns the correct fragment shader id to evaluate the copy operation for |
| 55 // the premultiply alpha pixel store settings and target. | 36 // the premultiply alpha pixel store settings and target. |
| 56 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, | 37 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, |
| 57 bool unpremultiply_alpha, | 38 bool unpremultiply_alpha, |
| 58 GLenum target) { | 39 GLenum target) { |
| 59 // Only one alpha mode at a time makes sense. | 40 // Only one alpha mode at a time makes sense. |
| 60 DCHECK(!premultiply_alpha || !unpremultiply_alpha); | 41 DCHECK(!premultiply_alpha || !unpremultiply_alpha); |
| 61 | 42 |
| 62 enum { | 43 enum { |
| 63 SAMPLER_2D, | 44 SAMPLER_2D, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 } | 90 } |
| 110 | 91 |
| 111 const char* kShaderPrecisionPreamble = "\ | 92 const char* kShaderPrecisionPreamble = "\ |
| 112 #ifdef GL_ES\n\ | 93 #ifdef GL_ES\n\ |
| 113 precision mediump float;\n\ | 94 precision mediump float;\n\ |
| 114 #define TexCoordPrecision mediump\n\ | 95 #define TexCoordPrecision mediump\n\ |
| 115 #else\n\ | 96 #else\n\ |
| 116 #define TexCoordPrecision\n\ | 97 #define TexCoordPrecision\n\ |
| 117 #endif\n"; | 98 #endif\n"; |
| 118 | 99 |
| 119 std::string GetVertexShaderSource(bool flip_y) { | 100 std::string GetVertexShaderSource() { |
| 120 std::string source; | 101 std::string source; |
| 121 | 102 |
| 122 // Preamble for core and compatibility mode. | 103 // Preamble for core and compatibility mode. |
| 123 if (gfx::GetGLImplementation() == | 104 if (gfx::GetGLImplementation() == |
| 124 gfx::kGLImplementationDesktopGLCoreProfile) { | 105 gfx::kGLImplementationDesktopGLCoreProfile) { |
| 125 source += std::string("\ | 106 source += std::string("\ |
| 126 #version 150\n\ | 107 #version 150\n\ |
| 127 #define ATTRIBUTE in\n\ | 108 #define ATTRIBUTE in\n\ |
| 128 #define VARYING out\n"); | 109 #define VARYING out\n"); |
| 129 } else { | 110 } else { |
| 130 source += std::string("\ | 111 source += std::string("\ |
| 131 #define ATTRIBUTE attribute\n\ | 112 #define ATTRIBUTE attribute\n\ |
| 132 #define VARYING varying\n"); | 113 #define VARYING varying\n"); |
| 133 } | 114 } |
| 134 | 115 |
| 135 // Preamble for texture precision. | 116 // Preamble for texture precision. |
| 136 source += std::string(kShaderPrecisionPreamble); | 117 source += std::string(kShaderPrecisionPreamble); |
| 137 | 118 |
| 138 // Preamble to differentiate based on |flip_y|. | |
| 139 if (flip_y) { | |
| 140 source += std::string("#define SIGN -\n"); | |
| 141 } else { | |
| 142 source += std::string("#define SIGN\n"); | |
| 143 } | |
| 144 | |
| 145 // Main shader source. | 119 // Main shader source. |
| 146 source += std::string("\ | 120 source += std::string("\ |
| 147 uniform vec2 u_vertex_translate;\n\ | 121 uniform vec2 u_vertex_dest_mult;\n\ |
| 148 uniform vec2 u_half_size;\n\ | 122 uniform vec2 u_vertex_dest_add;\n\ |
| 123 uniform vec2 u_vertex_source_mult;\n\ | |
| 124 uniform vec2 u_vertex_source_add;\n\ | |
| 149 ATTRIBUTE vec4 a_position;\n\ | 125 ATTRIBUTE vec4 a_position;\n\ |
| 150 VARYING TexCoordPrecision vec2 v_uv;\n\ | 126 VARYING TexCoordPrecision vec2 v_uv;\n\ |
| 151 void main(void) {\n\ | 127 void main(void) {\n\ |
| 152 gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);\n\ | 128 gl_Position = a_position;\n\ |
| 153 v_uv = a_position.xy * vec2(u_half_size.s, SIGN u_half_size.t) +\n\ | 129 gl_Position.xy = a_position.xy * u_vertex_dest_mult + \ |
| 154 vec2(u_half_size.s, u_half_size.t);\n\ | 130 u_vertex_dest_add;\n\ |
| 131 v_uv = a_position.xy * u_vertex_source_mult + u_vertex_source_add;\n\ | |
| 155 }\n"); | 132 }\n"); |
| 156 | 133 |
| 157 return source; | 134 return source; |
| 158 } | 135 } |
| 159 | 136 |
| 160 std::string GetFragmentShaderSource(bool premultiply_alpha, | 137 std::string GetFragmentShaderSource(bool premultiply_alpha, |
| 161 bool unpremultiply_alpha, | 138 bool unpremultiply_alpha, |
| 162 GLenum target) { | 139 GLenum target) { |
| 163 // Only one alpha mode at a time makes sense. | 140 // Only one alpha mode at a time makes sense. |
| 164 DCHECK(!premultiply_alpha || !unpremultiply_alpha); | 141 DCHECK(!premultiply_alpha || !unpremultiply_alpha); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 } | 260 } |
| 284 | 261 |
| 285 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder, | 262 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 286 GLenum source_target, | 263 GLenum source_target, |
| 287 GLuint source_id, | 264 GLuint source_id, |
| 288 GLuint dest_id, | 265 GLuint dest_id, |
| 289 GLenum dest_internal_format, | 266 GLenum dest_internal_format, |
| 290 GLsizei width, | 267 GLsizei width, |
| 291 GLsizei height, | 268 GLsizei height, |
| 292 GLuint framebuffer) { | 269 GLuint framebuffer) { |
| 293 DCHECK(source_target == GL_TEXTURE_2D || | 270 DCHECK(source_target == GL_TEXTURE_2D); |
| 294 source_target == GL_TEXTURE_RECTANGLE_ARB); | |
| 295 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 271 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| 296 glBindTexture(GL_TEXTURE_2D, dest_id); | 272 glBindTexture(GL_TEXTURE_2D, dest_id); |
| 297 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 273 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 298 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 274 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 301 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, | 277 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, |
| 302 0 /* x */, 0 /* y */, width, height, 0 /* border */); | 278 0 /* x */, 0 /* y */, width, height, 0 /* border */); |
| 303 } | 279 } |
| 304 | 280 |
| 305 decoder->RestoreTextureState(source_id); | 281 decoder->RestoreTextureState(source_id); |
| 306 decoder->RestoreTextureState(dest_id); | 282 decoder->RestoreTextureState(dest_id); |
| 307 decoder->RestoreTextureUnitBindings(0); | 283 decoder->RestoreTextureUnitBindings(0); |
| 308 decoder->RestoreActiveTexture(); | 284 decoder->RestoreActiveTexture(); |
| 309 decoder->RestoreFramebufferBindings(); | 285 decoder->RestoreFramebufferBindings(); |
| 310 } | 286 } |
| 311 | 287 |
| 312 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, | 288 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 313 GLenum source_target, | 289 GLenum source_target, |
| 314 GLuint source_id, | 290 GLuint source_id, |
| 291 GLenum dest_target, | |
| 315 GLuint dest_id, | 292 GLuint dest_id, |
| 316 GLint xoffset, | 293 GLint xoffset, |
| 317 GLint yoffset, | 294 GLint yoffset, |
| 318 GLint source_x, | 295 GLint source_x, |
| 319 GLint source_y, | 296 GLint source_y, |
| 320 GLsizei source_width, | 297 GLsizei source_width, |
| 321 GLsizei source_height, | 298 GLsizei source_height, |
| 322 GLuint framebuffer) { | 299 GLuint framebuffer) { |
| 323 DCHECK(source_target == GL_TEXTURE_2D || | 300 DCHECK(source_target == GL_TEXTURE_2D || |
| 324 source_target == GL_TEXTURE_RECTANGLE_ARB); | 301 source_target == GL_TEXTURE_RECTANGLE_ARB); |
| 325 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 302 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| 326 glBindTexture(GL_TEXTURE_2D, dest_id); | 303 glBindTexture(GL_TEXTURE_2D, dest_id); |
|
Zhenyao Mo
2016/01/04 22:43:54
Should you use dest_target here and in the followi
erikchen
2016/01/04 23:28:52
This function assumes that dest_target is GL_TEXTU
| |
| 327 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 304 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 328 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 305 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 307 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 331 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset, | 308 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset, |
| 332 source_x, source_y, source_width, source_height); | 309 source_x, source_y, source_width, source_height); |
| 333 } | 310 } |
| 334 | 311 |
| 335 decoder->RestoreTextureState(source_id); | 312 decoder->RestoreTextureState(source_id); |
| 336 decoder->RestoreTextureState(dest_id); | 313 decoder->RestoreTextureState(dest_id); |
| 337 decoder->RestoreTextureUnitBindings(0); | 314 decoder->RestoreTextureUnitBindings(0); |
| 338 decoder->RestoreActiveTexture(); | 315 decoder->RestoreActiveTexture(); |
| 339 decoder->RestoreFramebufferBindings(); | 316 decoder->RestoreFramebufferBindings(); |
| 340 } | 317 } |
| 341 | 318 |
| 342 } // namespace | 319 } // namespace |
| 343 | 320 |
| 344 namespace gpu { | 321 namespace gpu { |
| 345 | 322 |
| 346 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() | 323 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
| 347 : initialized_(false), | 324 : initialized_(false), |
| 348 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), | 325 vertex_shader_(0u), |
| 349 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), | 326 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), |
| 350 buffer_id_(0u), | 327 buffer_id_(0u), |
| 351 framebuffer_(0u) {} | 328 framebuffer_(0u) {} |
| 352 | 329 |
| 353 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { | 330 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { |
| 354 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is | 331 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is |
| 355 // lost, this class can be deleted without releasing resources like | 332 // lost, this class can be deleted without releasing resources like |
| 356 // GLES2DecoderImpl. | 333 // GLES2DecoderImpl. |
| 357 } | 334 } |
| 358 | 335 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 382 initialized_ = true; | 359 initialized_ = true; |
| 383 } | 360 } |
| 384 | 361 |
| 385 void CopyTextureCHROMIUMResourceManager::Destroy() { | 362 void CopyTextureCHROMIUMResourceManager::Destroy() { |
| 386 if (!initialized_) | 363 if (!initialized_) |
| 387 return; | 364 return; |
| 388 | 365 |
| 389 glDeleteFramebuffersEXT(1, &framebuffer_); | 366 glDeleteFramebuffersEXT(1, &framebuffer_); |
| 390 framebuffer_ = 0; | 367 framebuffer_ = 0; |
| 391 | 368 |
| 392 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); | 369 DeleteShader(vertex_shader_); |
| 393 std::for_each( | 370 std::for_each( |
| 394 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); | 371 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); |
| 395 | 372 |
| 396 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); | 373 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); |
| 397 ++it) { | 374 ++it) { |
| 398 const ProgramInfo& info = it->second; | 375 const ProgramInfo& info = it->second; |
| 399 glDeleteProgram(info.program); | 376 glDeleteProgram(info.program); |
| 400 } | 377 } |
| 401 | 378 |
| 402 glDeleteBuffersARB(1, &buffer_id_); | 379 glDeleteBuffersARB(1, &buffer_id_); |
| 403 buffer_id_ = 0; | 380 buffer_id_ = 0; |
| 404 } | 381 } |
| 405 | 382 |
| 406 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( | 383 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
| 407 const gles2::GLES2Decoder* decoder, | 384 const gles2::GLES2Decoder* decoder, |
| 408 GLenum source_target, | 385 GLenum source_target, |
| 409 GLuint source_id, | 386 GLuint source_id, |
| 410 GLenum source_internal_format, | 387 GLenum source_internal_format, |
| 388 GLenum dest_target, | |
| 411 GLuint dest_id, | 389 GLuint dest_id, |
| 412 GLenum dest_internal_format, | 390 GLenum dest_internal_format, |
| 413 GLsizei width, | 391 GLsizei width, |
| 414 GLsizei height, | 392 GLsizei height, |
| 415 bool flip_y, | 393 bool flip_y, |
| 416 bool premultiply_alpha, | 394 bool premultiply_alpha, |
| 417 bool unpremultiply_alpha) { | 395 bool unpremultiply_alpha) { |
| 418 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 396 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 419 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 397 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's |
| 420 // format does not contain a superset of the components required by the base | 398 // format does not contain a superset of the components required by the base |
| 421 // format of internalformat. | 399 // format of internalformat. |
| 422 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 400 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 423 bool source_format_contain_superset_of_dest_format = | 401 bool source_format_contain_superset_of_dest_format = |
| 424 (source_internal_format == dest_internal_format && | 402 (source_internal_format == dest_internal_format && |
| 425 source_internal_format != GL_BGRA_EXT) || | 403 source_internal_format != GL_BGRA_EXT) || |
| 426 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 404 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 427 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 405 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 428 // so restrict this to GL_TEXTURE_2D. | 406 // so restrict this to GL_TEXTURE_2D. |
| 429 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 407 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 408 !flip_y && !premultiply_alpha_change && | |
| 430 source_format_contain_superset_of_dest_format) { | 409 source_format_contain_superset_of_dest_format) { |
| 431 DoCopyTexImage2D(decoder, | 410 DoCopyTexImage2D(decoder, |
| 432 source_target, | 411 source_target, |
| 433 source_id, | 412 source_id, |
| 434 dest_id, | 413 dest_id, |
| 435 dest_internal_format, | 414 dest_internal_format, |
| 436 width, | 415 width, |
| 437 height, | 416 height, |
| 438 framebuffer_); | 417 framebuffer_); |
| 439 return; | 418 return; |
| 440 } | 419 } |
| 441 | 420 |
| 442 // Use kIdentityMatrix if no transform passed in. | 421 // Use kIdentityMatrix if no transform passed in. |
| 443 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width, | 422 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target, |
| 444 height, flip_y, premultiply_alpha, | 423 dest_id, width, height, flip_y, premultiply_alpha, |
| 445 unpremultiply_alpha, kIdentityMatrix); | 424 unpremultiply_alpha, kIdentityMatrix); |
| 446 } | 425 } |
| 447 | 426 |
| 448 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( | 427 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
| 449 const gles2::GLES2Decoder* decoder, | 428 const gles2::GLES2Decoder* decoder, |
| 450 GLenum source_target, | 429 GLenum source_target, |
| 451 GLuint source_id, | 430 GLuint source_id, |
| 452 GLenum source_internal_format, | 431 GLenum source_internal_format, |
| 432 GLenum dest_target, | |
| 453 GLuint dest_id, | 433 GLuint dest_id, |
| 454 GLenum dest_internal_format, | 434 GLenum dest_internal_format, |
| 455 GLint xoffset, | 435 GLint xoffset, |
| 456 GLint yoffset, | 436 GLint yoffset, |
| 457 GLint x, | 437 GLint x, |
| 458 GLint y, | 438 GLint y, |
| 459 GLsizei width, | 439 GLsizei width, |
| 460 GLsizei height, | 440 GLsizei height, |
| 461 GLsizei dest_width, | 441 GLsizei dest_width, |
| 462 GLsizei dest_height, | 442 GLsizei dest_height, |
| 463 GLsizei source_width, | 443 GLsizei source_width, |
| 464 GLsizei source_height, | 444 GLsizei source_height, |
| 465 bool flip_y, | 445 bool flip_y, |
| 466 bool premultiply_alpha, | 446 bool premultiply_alpha, |
| 467 bool unpremultiply_alpha) { | 447 bool unpremultiply_alpha) { |
| 468 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 448 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 469 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 449 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's |
| 470 // format does not contain a superset of the components required by the base | 450 // format does not contain a superset of the components required by the base |
| 471 // format of internalformat. | 451 // format of internalformat. |
| 472 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 452 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 473 bool source_format_contain_superset_of_dest_format = | 453 bool source_format_contain_superset_of_dest_format = |
| 474 (source_internal_format == dest_internal_format && | 454 (source_internal_format == dest_internal_format && |
| 475 source_internal_format != GL_BGRA_EXT) || | 455 source_internal_format != GL_BGRA_EXT) || |
| 476 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 456 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 477 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 457 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 478 // so restrict this to GL_TEXTURE_2D. | 458 // so restrict this to GL_TEXTURE_2D. |
| 479 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 459 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 460 !flip_y && !premultiply_alpha_change && | |
| 480 source_format_contain_superset_of_dest_format) { | 461 source_format_contain_superset_of_dest_format) { |
| 481 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, | 462 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_target, dest_id, |
| 482 yoffset, x, y, width, height, framebuffer_); | 463 xoffset, yoffset, x, y, width, height, framebuffer_); |
| 483 return; | 464 return; |
| 484 } | 465 } |
| 485 | 466 |
| 486 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, | 467 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 487 yoffset, x, y, width, height, dest_width, dest_height, | 468 xoffset, yoffset, x, y, width, height, dest_width, dest_height, |
| 488 source_width, source_height, flip_y, premultiply_alpha, | 469 source_width, source_height, flip_y, premultiply_alpha, |
| 489 unpremultiply_alpha, kIdentityMatrix); | 470 unpremultiply_alpha, kIdentityMatrix); |
| 490 } | 471 } |
| 491 | 472 |
| 492 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( | 473 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
| 493 const gles2::GLES2Decoder* decoder, | 474 const gles2::GLES2Decoder* decoder, |
| 494 GLenum source_target, | 475 GLenum source_target, |
| 495 GLuint source_id, | 476 GLuint source_id, |
| 477 GLenum dest_target, | |
| 496 GLuint dest_id, | 478 GLuint dest_id, |
| 497 GLsizei width, | 479 GLsizei width, |
| 498 GLsizei height, | 480 GLsizei height, |
| 499 bool flip_y, | 481 bool flip_y, |
| 500 bool premultiply_alpha, | 482 bool premultiply_alpha, |
| 501 bool unpremultiply_alpha, | 483 bool unpremultiply_alpha, |
| 502 const GLfloat transform_matrix[16]) { | 484 const GLfloat transform_matrix[16]) { |
| 503 GLsizei dest_width = width; | 485 GLsizei dest_width = width; |
| 504 GLsizei dest_height = height; | 486 GLsizei dest_height = height; |
| 505 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0, | 487 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 506 width, height, dest_width, dest_height, width, height, | 488 0, 0, 0, 0, width, height, dest_width, dest_height, |
| 507 flip_y, premultiply_alpha, unpremultiply_alpha, | 489 width, height, flip_y, premultiply_alpha, |
| 508 transform_matrix); | 490 unpremultiply_alpha, transform_matrix); |
| 509 } | 491 } |
| 510 | 492 |
| 511 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( | 493 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
| 512 const gles2::GLES2Decoder* decoder, | 494 const gles2::GLES2Decoder* decoder, |
| 513 GLenum source_target, | 495 GLenum source_target, |
| 514 GLuint source_id, | 496 GLuint source_id, |
| 497 GLenum dest_target, | |
| 515 GLuint dest_id, | 498 GLuint dest_id, |
| 516 GLint xoffset, | 499 GLint xoffset, |
| 517 GLint yoffset, | 500 GLint yoffset, |
| 518 GLint x, | 501 GLint x, |
| 519 GLint y, | 502 GLint y, |
| 520 GLsizei width, | 503 GLsizei width, |
| 521 GLsizei height, | 504 GLsizei height, |
| 522 GLsizei dest_width, | 505 GLsizei dest_width, |
| 523 GLsizei dest_height, | 506 GLsizei dest_height, |
| 524 GLsizei source_width, | 507 GLsizei source_width, |
| 525 GLsizei source_height, | 508 GLsizei source_height, |
| 526 bool flip_y, | 509 bool flip_y, |
| 527 bool premultiply_alpha, | 510 bool premultiply_alpha, |
| 528 bool unpremultiply_alpha, | 511 bool unpremultiply_alpha, |
| 529 const GLfloat transform_matrix[16]) { | 512 const GLfloat transform_matrix[16]) { |
| 530 DCHECK(source_target == GL_TEXTURE_2D || | 513 DCHECK(source_target == GL_TEXTURE_2D || |
| 531 source_target == GL_TEXTURE_RECTANGLE_ARB || | 514 source_target == GL_TEXTURE_RECTANGLE_ARB || |
| 532 source_target == GL_TEXTURE_EXTERNAL_OES); | 515 source_target == GL_TEXTURE_EXTERNAL_OES); |
| 516 DCHECK(dest_target == GL_TEXTURE_2D || | |
| 517 dest_target == GL_TEXTURE_RECTANGLE_ARB); | |
| 533 DCHECK_GE(xoffset, 0); | 518 DCHECK_GE(xoffset, 0); |
| 534 DCHECK_LE(xoffset + width, dest_width); | 519 DCHECK_LE(xoffset + width, dest_width); |
| 535 DCHECK_GE(yoffset, 0); | 520 DCHECK_GE(yoffset, 0); |
| 536 DCHECK_LE(yoffset + height, dest_height); | 521 DCHECK_LE(yoffset + height, dest_height); |
| 522 if (dest_width == 0 || dest_height == 0 || source_width == 0 || | |
| 523 source_height == 0) { | |
| 524 return; | |
| 525 } | |
| 526 | |
| 537 if (!initialized_) { | 527 if (!initialized_) { |
| 538 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; | 528 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; |
| 539 return; | 529 return; |
| 540 } | 530 } |
| 541 | 531 |
| 542 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y); | |
| 543 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); | |
| 544 FragmentShaderId fragment_shader_id = GetFragmentShaderId( | 532 FragmentShaderId fragment_shader_id = GetFragmentShaderId( |
| 545 premultiply_alpha, unpremultiply_alpha, source_target); | 533 premultiply_alpha, unpremultiply_alpha, source_target); |
| 546 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); | 534 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); |
| 547 | 535 |
| 548 ProgramMapKey key(vertex_shader_id, fragment_shader_id); | 536 ProgramMapKey key(fragment_shader_id); |
| 549 ProgramInfo* info = &programs_[key]; | 537 ProgramInfo* info = &programs_[key]; |
| 550 // Create program if necessary. | 538 // Create program if necessary. |
| 551 if (!info->program) { | 539 if (!info->program) { |
| 552 info->program = glCreateProgram(); | 540 info->program = glCreateProgram(); |
| 553 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; | 541 if (!vertex_shader_) { |
| 554 if (!*vertex_shader) { | 542 vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); |
| 555 *vertex_shader = glCreateShader(GL_VERTEX_SHADER); | 543 std::string source = GetVertexShaderSource(); |
| 556 std::string source = GetVertexShaderSource(flip_y); | 544 CompileShader(vertex_shader_, source.c_str()); |
| 557 CompileShader(*vertex_shader, source.c_str()); | |
| 558 } | 545 } |
| 559 glAttachShader(info->program, *vertex_shader); | 546 glAttachShader(info->program, vertex_shader_); |
| 560 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; | 547 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; |
| 561 if (!*fragment_shader) { | 548 if (!*fragment_shader) { |
| 562 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); | 549 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); |
| 563 std::string source = GetFragmentShaderSource( | 550 std::string source = GetFragmentShaderSource( |
| 564 premultiply_alpha, unpremultiply_alpha, source_target); | 551 premultiply_alpha, unpremultiply_alpha, source_target); |
| 565 CompileShader(*fragment_shader, source.c_str()); | 552 CompileShader(*fragment_shader, source.c_str()); |
| 566 } | 553 } |
| 567 glAttachShader(info->program, *fragment_shader); | 554 glAttachShader(info->program, *fragment_shader); |
| 568 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); | 555 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); |
| 569 glLinkProgram(info->program); | 556 glLinkProgram(info->program); |
| 570 #ifndef NDEBUG | 557 #ifndef NDEBUG |
| 571 GLint linked; | 558 GLint linked; |
| 572 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); | 559 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); |
| 573 if (!linked) | 560 if (!linked) |
| 574 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; | 561 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; |
| 575 #endif | 562 #endif |
| 576 info->vertex_translate_handle = glGetUniformLocation(info->program, | 563 info->vertex_dest_mult_handle = |
| 577 "u_vertex_translate"); | 564 glGetUniformLocation(info->program, "u_vertex_dest_mult"); |
| 565 info->vertex_dest_add_handle = | |
| 566 glGetUniformLocation(info->program, "u_vertex_dest_add"); | |
| 567 info->vertex_source_mult_handle = | |
| 568 glGetUniformLocation(info->program, "u_vertex_source_mult"); | |
| 569 info->vertex_source_add_handle = | |
| 570 glGetUniformLocation(info->program, "u_vertex_source_add"); | |
| 571 | |
| 578 info->tex_coord_transform_handle = | 572 info->tex_coord_transform_handle = |
| 579 glGetUniformLocation(info->program, "u_tex_coord_transform"); | 573 glGetUniformLocation(info->program, "u_tex_coord_transform"); |
| 580 info->half_size_handle = glGetUniformLocation(info->program, "u_half_size"); | |
| 581 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); | 574 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); |
| 582 } | 575 } |
| 583 glUseProgram(info->program); | 576 glUseProgram(info->program); |
| 584 | 577 |
| 585 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, | 578 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, |
| 586 transform_matrix); | 579 transform_matrix); |
| 587 | 580 |
| 588 GLint x_translate = xoffset - x; | 581 // Note: For simplicity, the calculations in this comment block use a single |
| 589 GLint y_translate = yoffset - y; | 582 // dimension. All calculations trivially extend to the x-y plane. |
| 590 if (!x_translate && !y_translate) { | 583 // The target subrange in the destination texture has coordinates |
| 591 glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f); | 584 // [xoffset, xoffset + width]. The full destination texture has range |
| 592 } else { | 585 // [0, dest_width]. |
| 593 // transform offsets from ([0, dest_width], [0, dest_height]) coord. | 586 // |
| 594 // to ([-1, 1], [-1, 1]) coord. | 587 // We want to find A and B such that: |
| 595 GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width); | 588 // A * X + B = Y |
| 596 GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height); | 589 // C * Y + D = Z |
| 590 // | |
| 591 // where X = [-1, 1], Z = [xoffset, xoffset + width] | |
| 592 // and C, D satisfy the relationship C * [-1, 1] + D = [0, dest_width]. | |
| 593 // | |
| 594 // Math shows: | |
| 595 // C = D = dest_width / 2 | |
| 596 // Y = [(xoffset * 2 / dest_width) - 1, | |
| 597 // (xoffset + width) * 2 / dest_width) - 1] | |
| 598 // A = width / dest_width | |
| 599 // B = (xoffset * 2 + width - dest_width) / dest_width | |
| 600 glUniform2f(info->vertex_dest_mult_handle, width * 1.f / dest_width, | |
| 601 height * 1.f / dest_height); | |
| 602 glUniform2f(info->vertex_dest_add_handle, | |
| 603 (xoffset * 2.f + width - dest_width) / dest_width, | |
| 604 (yoffset * 2.f + height - dest_height) / dest_height); | |
| 597 | 605 |
| 598 // Pass translation to the shader program. | 606 // Note: For simplicity, the calculations in this comment block use a single |
| 599 glUniform2f(info->vertex_translate_handle, x_translate_on_vertex, | 607 // dimension. All calculations trivially extend to the x-y plane. |
| 600 y_translate_on_vertex); | 608 // The target subrange in the source texture has coordinates [x, x + width]. |
| 601 } | 609 // The full source texture has range [0, source_width]. We need to transform |
| 602 if (source_target == GL_TEXTURE_RECTANGLE_ARB) | 610 // the subrange into texture space ([0, M]), assuming that [0, source_width] |
| 603 glUniform2f(info->half_size_handle, source_width / 2.0f, | 611 // gets mapped to [0, M]. If source_target == GL_TEXTURE_RECTANGLE_ARB, M = |
| 604 source_height / 2.0f); | 612 // source_width. Otherwise, M = 1. |
| 605 else | 613 // |
| 606 glUniform2f(info->half_size_handle, 0.5f, 0.5f); | 614 // We want to find A and B such that: |
| 615 // A * X + B = Y | |
| 616 // C * Y + D = Z | |
| 617 // | |
| 618 // where X = [-1, 1], Z = [x, x + width] | |
| 619 // and C, D satisfy the relationship C * [0, M] + D = [0, source_width]. | |
| 620 // | |
| 621 // Math shows: | |
| 622 // D = 0 | |
| 623 // C = source_width / M | |
| 624 // Y = [x * M / source_width, (x + width) * M / source_width] | |
| 625 // B = (x + w/2) * M / source_width | |
| 626 // A = (w/2) * M / source_width | |
| 627 // | |
| 628 // When flip_y is true, we run the same calcluation, but with Z = [x + width, | |
| 629 // x]. (I'm intentionally keeping the x-plane notation, although the | |
| 630 // calculation only gets applied to the y-plane). | |
| 631 // | |
| 632 // Math shows: | |
| 633 // D = 0 | |
| 634 // C = source_width / M | |
| 635 // Y = [(x + width) * M / source_width, x * M / source_width] | |
| 636 // B = (x + w/2) * M / source_width | |
| 637 // A = (-w/2) * M / source_width | |
| 638 // | |
| 639 // So everything is the same but the sign of A is flipped. | |
| 640 GLfloat m_x = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_width : 1; | |
| 641 GLfloat m_y = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_height : 1; | |
| 642 GLfloat sign_a = flip_y ? -1 : 1; | |
| 643 glUniform2f(info->vertex_source_mult_handle, width / 2.f * m_x / source_width, | |
| 644 height / 2.f * m_y / source_height * sign_a); | |
| 645 glUniform2f(info->vertex_source_add_handle, | |
| 646 (x + width / 2.f) * m_x / source_width, | |
| 647 (y + height / 2.f) * m_y / source_height); | |
| 607 | 648 |
| 608 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) { | 649 if (BindFramebufferTexture2D(dest_target, dest_id, framebuffer_)) { |
| 609 #ifndef NDEBUG | 650 #ifndef NDEBUG |
| 610 // glValidateProgram of MACOSX validates FBO unlike other platforms, so | 651 // glValidateProgram of MACOSX validates FBO unlike other platforms, so |
| 611 // glValidateProgram must be called after FBO binding. crbug.com/463439 | 652 // glValidateProgram must be called after FBO binding. crbug.com/463439 |
| 612 glValidateProgram(info->program); | 653 glValidateProgram(info->program); |
| 613 GLint validation_status; | 654 GLint validation_status; |
| 614 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); | 655 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); |
| 615 if (GL_TRUE != validation_status) { | 656 if (GL_TRUE != validation_status) { |
| 616 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; | 657 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; |
| 617 return; | 658 return; |
| 618 } | 659 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 decoder->RestoreTextureState(dest_id); | 700 decoder->RestoreTextureState(dest_id); |
| 660 decoder->RestoreTextureUnitBindings(0); | 701 decoder->RestoreTextureUnitBindings(0); |
| 661 decoder->RestoreActiveTexture(); | 702 decoder->RestoreActiveTexture(); |
| 662 decoder->RestoreProgramBindings(); | 703 decoder->RestoreProgramBindings(); |
| 663 decoder->RestoreBufferBindings(); | 704 decoder->RestoreBufferBindings(); |
| 664 decoder->RestoreFramebufferBindings(); | 705 decoder->RestoreFramebufferBindings(); |
| 665 decoder->RestoreGlobalState(); | 706 decoder->RestoreGlobalState(); |
| 666 } | 707 } |
| 667 | 708 |
| 668 } // namespace gpu | 709 } // namespace gpu |
| OLD | NEW |